diff options
Diffstat (limited to 'drivers/usb/serial/symbolserial.c')
-rw-r--r-- | drivers/usb/serial/symbolserial.c | 130 |
1 files changed, 28 insertions, 102 deletions
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index be05e6caf9a3..9b1648945e7a 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Symbol USB barcode to serial driver | 2 | * Symbol USB barcode to serial driver |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com> | ||
4 | * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de> | 5 | * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de> |
5 | * Copyright (C) 2009 Novell Inc. | 6 | * Copyright (C) 2009 Novell Inc. |
6 | * | 7 | * |
@@ -26,27 +27,17 @@ static const struct usb_device_id id_table[] = { | |||
26 | }; | 27 | }; |
27 | MODULE_DEVICE_TABLE(usb, id_table); | 28 | MODULE_DEVICE_TABLE(usb, id_table); |
28 | 29 | ||
29 | /* This structure holds all of the individual device information */ | ||
30 | struct symbol_private { | 30 | struct symbol_private { |
31 | struct usb_device *udev; | ||
32 | struct usb_serial *serial; | ||
33 | struct usb_serial_port *port; | ||
34 | unsigned char *int_buffer; | ||
35 | struct urb *int_urb; | ||
36 | int buffer_size; | ||
37 | u8 bInterval; | ||
38 | u8 int_address; | ||
39 | spinlock_t lock; /* protects the following flags */ | 31 | spinlock_t lock; /* protects the following flags */ |
40 | bool throttled; | 32 | bool throttled; |
41 | bool actually_throttled; | 33 | bool actually_throttled; |
42 | bool rts; | ||
43 | }; | 34 | }; |
44 | 35 | ||
45 | static void symbol_int_callback(struct urb *urb) | 36 | static void symbol_int_callback(struct urb *urb) |
46 | { | 37 | { |
47 | struct symbol_private *priv = urb->context; | 38 | struct usb_serial_port *port = urb->context; |
39 | struct symbol_private *priv = usb_get_serial_port_data(port); | ||
48 | unsigned char *data = urb->transfer_buffer; | 40 | unsigned char *data = urb->transfer_buffer; |
49 | struct usb_serial_port *port = priv->port; | ||
50 | int status = urb->status; | 41 | int status = urb->status; |
51 | int result; | 42 | int result; |
52 | int data_length; | 43 | int data_length; |
@@ -84,7 +75,7 @@ static void symbol_int_callback(struct urb *urb) | |||
84 | tty_insert_flip_string(&port->port, &data[1], data_length); | 75 | tty_insert_flip_string(&port->port, &data[1], data_length); |
85 | tty_flip_buffer_push(&port->port); | 76 | tty_flip_buffer_push(&port->port); |
86 | } else { | 77 | } else { |
87 | dev_dbg(&priv->udev->dev, | 78 | dev_dbg(&port->dev, |
88 | "Improper amount of data received from the device, " | 79 | "Improper amount of data received from the device, " |
89 | "%d bytes", urb->actual_length); | 80 | "%d bytes", urb->actual_length); |
90 | } | 81 | } |
@@ -94,12 +85,7 @@ exit: | |||
94 | 85 | ||
95 | /* Continue trying to always read if we should */ | 86 | /* Continue trying to always read if we should */ |
96 | if (!priv->throttled) { | 87 | if (!priv->throttled) { |
97 | usb_fill_int_urb(priv->int_urb, priv->udev, | 88 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); |
98 | usb_rcvintpipe(priv->udev, | ||
99 | priv->int_address), | ||
100 | priv->int_buffer, priv->buffer_size, | ||
101 | symbol_int_callback, priv, priv->bInterval); | ||
102 | result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); | ||
103 | if (result) | 89 | if (result) |
104 | dev_err(&port->dev, | 90 | dev_err(&port->dev, |
105 | "%s - failed resubmitting read urb, error %d\n", | 91 | "%s - failed resubmitting read urb, error %d\n", |
@@ -118,15 +104,10 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
118 | spin_lock_irqsave(&priv->lock, flags); | 104 | spin_lock_irqsave(&priv->lock, flags); |
119 | priv->throttled = false; | 105 | priv->throttled = false; |
120 | priv->actually_throttled = false; | 106 | priv->actually_throttled = false; |
121 | priv->port = port; | ||
122 | spin_unlock_irqrestore(&priv->lock, flags); | 107 | spin_unlock_irqrestore(&priv->lock, flags); |
123 | 108 | ||
124 | /* Start reading from the device */ | 109 | /* Start reading from the device */ |
125 | usb_fill_int_urb(priv->int_urb, priv->udev, | 110 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
126 | usb_rcvintpipe(priv->udev, priv->int_address), | ||
127 | priv->int_buffer, priv->buffer_size, | ||
128 | symbol_int_callback, priv, priv->bInterval); | ||
129 | result = usb_submit_urb(priv->int_urb, GFP_KERNEL); | ||
130 | if (result) | 111 | if (result) |
131 | dev_err(&port->dev, | 112 | dev_err(&port->dev, |
132 | "%s - failed resubmitting read urb, error %d\n", | 113 | "%s - failed resubmitting read urb, error %d\n", |
@@ -136,10 +117,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
136 | 117 | ||
137 | static void symbol_close(struct usb_serial_port *port) | 118 | static void symbol_close(struct usb_serial_port *port) |
138 | { | 119 | { |
139 | struct symbol_private *priv = usb_get_serial_data(port->serial); | 120 | usb_kill_urb(port->interrupt_in_urb); |
140 | |||
141 | /* shutdown our urbs */ | ||
142 | usb_kill_urb(priv->int_urb); | ||
143 | } | 121 | } |
144 | 122 | ||
145 | static void symbol_throttle(struct tty_struct *tty) | 123 | static void symbol_throttle(struct tty_struct *tty) |
@@ -166,7 +144,7 @@ static void symbol_unthrottle(struct tty_struct *tty) | |||
166 | spin_unlock_irq(&priv->lock); | 144 | spin_unlock_irq(&priv->lock); |
167 | 145 | ||
168 | if (was_throttled) { | 146 | if (was_throttled) { |
169 | result = usb_submit_urb(priv->int_urb, GFP_KERNEL); | 147 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
170 | if (result) | 148 | if (result) |
171 | dev_err(&port->dev, | 149 | dev_err(&port->dev, |
172 | "%s - failed submitting read urb, error %d\n", | 150 | "%s - failed submitting read urb, error %d\n", |
@@ -176,89 +154,36 @@ static void symbol_unthrottle(struct tty_struct *tty) | |||
176 | 154 | ||
177 | static int symbol_startup(struct usb_serial *serial) | 155 | static int symbol_startup(struct usb_serial *serial) |
178 | { | 156 | { |
157 | if (!serial->num_interrupt_in) { | ||
158 | dev_err(&serial->dev->dev, "no interrupt-in endpoint\n"); | ||
159 | return -ENODEV; | ||
160 | } | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int symbol_port_probe(struct usb_serial_port *port) | ||
166 | { | ||
179 | struct symbol_private *priv; | 167 | struct symbol_private *priv; |
180 | struct usb_host_interface *intf; | ||
181 | int i; | ||
182 | int retval = -ENOMEM; | ||
183 | bool int_in_found = false; | ||
184 | 168 | ||
185 | /* create our private serial structure */ | ||
186 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 169 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
187 | if (priv == NULL) { | 170 | if (!priv) |
188 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); | ||
189 | return -ENOMEM; | 171 | return -ENOMEM; |
190 | } | 172 | |
191 | spin_lock_init(&priv->lock); | 173 | spin_lock_init(&priv->lock); |
192 | priv->serial = serial; | ||
193 | priv->port = serial->port[0]; | ||
194 | priv->udev = serial->dev; | ||
195 | |||
196 | /* find our interrupt endpoint */ | ||
197 | intf = serial->interface->altsetting; | ||
198 | for (i = 0; i < intf->desc.bNumEndpoints; ++i) { | ||
199 | struct usb_endpoint_descriptor *endpoint; | ||
200 | |||
201 | endpoint = &intf->endpoint[i].desc; | ||
202 | if (!usb_endpoint_is_int_in(endpoint)) | ||
203 | continue; | ||
204 | |||
205 | priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
206 | if (!priv->int_urb) { | ||
207 | dev_err(&priv->udev->dev, "out of memory\n"); | ||
208 | goto error; | ||
209 | } | ||
210 | |||
211 | priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; | ||
212 | priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); | ||
213 | if (!priv->int_buffer) { | ||
214 | dev_err(&priv->udev->dev, "out of memory\n"); | ||
215 | goto error; | ||
216 | } | ||
217 | |||
218 | priv->int_address = endpoint->bEndpointAddress; | ||
219 | priv->bInterval = endpoint->bInterval; | ||
220 | |||
221 | /* set up our int urb */ | ||
222 | usb_fill_int_urb(priv->int_urb, priv->udev, | ||
223 | usb_rcvintpipe(priv->udev, | ||
224 | endpoint->bEndpointAddress), | ||
225 | priv->int_buffer, priv->buffer_size, | ||
226 | symbol_int_callback, priv, priv->bInterval); | ||
227 | |||
228 | int_in_found = true; | ||
229 | break; | ||
230 | } | ||
231 | 174 | ||
232 | if (!int_in_found) { | 175 | usb_set_serial_port_data(port, priv); |
233 | dev_err(&priv->udev->dev, | ||
234 | "Error - the proper endpoints were not found!\n"); | ||
235 | goto error; | ||
236 | } | ||
237 | 176 | ||
238 | usb_set_serial_data(serial, priv); | ||
239 | return 0; | 177 | return 0; |
240 | |||
241 | error: | ||
242 | usb_free_urb(priv->int_urb); | ||
243 | kfree(priv->int_buffer); | ||
244 | kfree(priv); | ||
245 | return retval; | ||
246 | } | ||
247 | |||
248 | static void symbol_disconnect(struct usb_serial *serial) | ||
249 | { | ||
250 | struct symbol_private *priv = usb_get_serial_data(serial); | ||
251 | |||
252 | usb_kill_urb(priv->int_urb); | ||
253 | usb_free_urb(priv->int_urb); | ||
254 | } | 178 | } |
255 | 179 | ||
256 | static void symbol_release(struct usb_serial *serial) | 180 | static int symbol_port_remove(struct usb_serial_port *port) |
257 | { | 181 | { |
258 | struct symbol_private *priv = usb_get_serial_data(serial); | 182 | struct symbol_private *priv = usb_get_serial_port_data(port); |
259 | 183 | ||
260 | kfree(priv->int_buffer); | ||
261 | kfree(priv); | 184 | kfree(priv); |
185 | |||
186 | return 0; | ||
262 | } | 187 | } |
263 | 188 | ||
264 | static struct usb_serial_driver symbol_device = { | 189 | static struct usb_serial_driver symbol_device = { |
@@ -269,12 +194,13 @@ static struct usb_serial_driver symbol_device = { | |||
269 | .id_table = id_table, | 194 | .id_table = id_table, |
270 | .num_ports = 1, | 195 | .num_ports = 1, |
271 | .attach = symbol_startup, | 196 | .attach = symbol_startup, |
197 | .port_probe = symbol_port_probe, | ||
198 | .port_remove = symbol_port_remove, | ||
272 | .open = symbol_open, | 199 | .open = symbol_open, |
273 | .close = symbol_close, | 200 | .close = symbol_close, |
274 | .disconnect = symbol_disconnect, | ||
275 | .release = symbol_release, | ||
276 | .throttle = symbol_throttle, | 201 | .throttle = symbol_throttle, |
277 | .unthrottle = symbol_unthrottle, | 202 | .unthrottle = symbol_unthrottle, |
203 | .read_int_callback = symbol_int_callback, | ||
278 | }; | 204 | }; |
279 | 205 | ||
280 | static struct usb_serial_driver * const serial_drivers[] = { | 206 | static struct usb_serial_driver * const serial_drivers[] = { |