]>
Commit | Line | Data |
---|---|---|
4d7b5c7f TH |
1 | /* |
2 | * Copyright (C) 2003-2008 Takahiro Hirofuchi | |
3 | * | |
4 | * This is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
17 | * USA. | |
18 | */ | |
19 | ||
5a0e3ad6 TH |
20 | #include <linux/slab.h> |
21 | ||
4d7b5c7f TH |
22 | #include "usbip_common.h" |
23 | #include "stub.h" | |
27729aad | 24 | #include <linux/usb/hcd.h> |
4d7b5c7f TH |
25 | |
26 | ||
27 | static int is_clear_halt_cmd(struct urb *urb) | |
28 | { | |
29 | struct usb_ctrlrequest *req; | |
30 | ||
31 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
32 | ||
33 | return (req->bRequest == USB_REQ_CLEAR_FEATURE) && | |
34 | (req->bRequestType == USB_RECIP_ENDPOINT) && | |
35 | (req->wValue == USB_ENDPOINT_HALT); | |
36 | } | |
37 | ||
38 | static int is_set_interface_cmd(struct urb *urb) | |
39 | { | |
40 | struct usb_ctrlrequest *req; | |
41 | ||
42 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
43 | ||
44 | return (req->bRequest == USB_REQ_SET_INTERFACE) && | |
45 | (req->bRequestType == USB_RECIP_INTERFACE); | |
46 | } | |
47 | ||
48 | static int is_set_configuration_cmd(struct urb *urb) | |
49 | { | |
50 | struct usb_ctrlrequest *req; | |
51 | ||
52 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
53 | ||
54 | return (req->bRequest == USB_REQ_SET_CONFIGURATION) && | |
55 | (req->bRequestType == USB_RECIP_DEVICE); | |
56 | } | |
57 | ||
58 | static int is_reset_device_cmd(struct urb *urb) | |
59 | { | |
60 | struct usb_ctrlrequest *req; | |
61 | __u16 value; | |
62 | __u16 index; | |
63 | ||
64 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
65 | value = le16_to_cpu(req->wValue); | |
66 | index = le16_to_cpu(req->wIndex); | |
67 | ||
68 | if ((req->bRequest == USB_REQ_SET_FEATURE) && | |
69 | (req->bRequestType == USB_RT_PORT) && | |
b8868e45 BM |
70 | (value == USB_PORT_FEAT_RESET)) { |
71 | usbip_dbg_stub_rx("reset_device_cmd, port %u\n", index); | |
4d7b5c7f TH |
72 | return 1; |
73 | } else | |
74 | return 0; | |
75 | } | |
76 | ||
77 | static int tweak_clear_halt_cmd(struct urb *urb) | |
78 | { | |
79 | struct usb_ctrlrequest *req; | |
80 | int target_endp; | |
81 | int target_dir; | |
82 | int target_pipe; | |
83 | int ret; | |
84 | ||
85 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
86 | ||
87 | /* | |
88 | * The stalled endpoint is specified in the wIndex value. The endpoint | |
89 | * of the urb is the target of this clear_halt request (i.e., control | |
90 | * endpoint). | |
91 | */ | |
92 | target_endp = le16_to_cpu(req->wIndex) & 0x000f; | |
93 | ||
94 | /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */ | |
95 | target_dir = le16_to_cpu(req->wIndex) & 0x0080; | |
96 | ||
97 | if (target_dir) | |
98 | target_pipe = usb_rcvctrlpipe(urb->dev, target_endp); | |
99 | else | |
100 | target_pipe = usb_sndctrlpipe(urb->dev, target_endp); | |
101 | ||
102 | ret = usb_clear_halt(urb->dev, target_pipe); | |
103 | if (ret < 0) | |
b8868e45 BM |
104 | usbip_uinfo("clear_halt error: devnum %d endp %d, %d\n", |
105 | urb->dev->devnum, target_endp, ret); | |
4d7b5c7f | 106 | else |
b8868e45 BM |
107 | usbip_uinfo("clear_halt done: devnum %d endp %d\n", |
108 | urb->dev->devnum, target_endp); | |
4d7b5c7f TH |
109 | |
110 | return ret; | |
111 | } | |
112 | ||
113 | static int tweak_set_interface_cmd(struct urb *urb) | |
114 | { | |
115 | struct usb_ctrlrequest *req; | |
116 | __u16 alternate; | |
117 | __u16 interface; | |
118 | int ret; | |
119 | ||
120 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
121 | alternate = le16_to_cpu(req->wValue); | |
122 | interface = le16_to_cpu(req->wIndex); | |
123 | ||
b8868e45 BM |
124 | usbip_dbg_stub_rx("set_interface: inf %u alt %u\n", interface, |
125 | alternate); | |
4d7b5c7f TH |
126 | |
127 | ret = usb_set_interface(urb->dev, interface, alternate); | |
128 | if (ret < 0) | |
b8868e45 BM |
129 | usbip_uinfo("set_interface error: inf %u alt %u, %d\n", |
130 | interface, alternate, ret); | |
4d7b5c7f | 131 | else |
b8868e45 | 132 | usbip_uinfo("set_interface done: inf %u alt %u\n", |
4d7b5c7f TH |
133 | interface, |
134 | alternate); | |
135 | ||
136 | return ret; | |
137 | } | |
138 | ||
139 | static int tweak_set_configuration_cmd(struct urb *urb) | |
140 | { | |
141 | struct usb_ctrlrequest *req; | |
142 | __u16 config; | |
143 | ||
144 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
145 | config = le16_to_cpu(req->wValue); | |
146 | ||
147 | /* | |
148 | * I have never seen a multi-config device. Very rare. | |
149 | * For most devices, this will be called to choose a default | |
150 | * configuration only once in an initialization phase. | |
151 | * | |
152 | * set_configuration may change a device configuration and its device | |
153 | * drivers will be unbound and assigned for a new device configuration. | |
154 | * This means this usbip driver will be also unbound when called, then | |
155 | * eventually reassigned to the device as far as driver matching | |
156 | * condition is kept. | |
157 | * | |
158 | * Unfortunatelly, an existing usbip connection will be dropped | |
159 | * due to this driver unbinding. So, skip here. | |
160 | * A user may need to set a special configuration value before | |
161 | * exporting the device. | |
162 | */ | |
b8868e45 BM |
163 | usbip_uinfo("set_configuration (%d) to %s\n", config, |
164 | dev_name(&urb->dev->dev)); | |
165 | usbip_uinfo("but, skip!\n"); | |
4d7b5c7f TH |
166 | |
167 | return 0; | |
168 | /* return usb_driver_set_configuration(urb->dev, config); */ | |
169 | } | |
170 | ||
171 | static int tweak_reset_device_cmd(struct urb *urb) | |
172 | { | |
173 | struct usb_ctrlrequest *req; | |
174 | __u16 value; | |
175 | __u16 index; | |
176 | int ret; | |
177 | ||
178 | req = (struct usb_ctrlrequest *) urb->setup_packet; | |
179 | value = le16_to_cpu(req->wValue); | |
180 | index = le16_to_cpu(req->wIndex); | |
181 | ||
b8868e45 BM |
182 | usbip_uinfo("reset_device (port %d) to %s\n", index, |
183 | dev_name(&urb->dev->dev)); | |
4d7b5c7f TH |
184 | |
185 | /* all interfaces should be owned by usbip driver, so just reset it. */ | |
186 | ret = usb_lock_device_for_reset(urb->dev, NULL); | |
187 | if (ret < 0) { | |
188 | dev_err(&urb->dev->dev, "lock for reset\n"); | |
189 | return ret; | |
190 | } | |
191 | ||
192 | /* try to reset the device */ | |
193 | ret = usb_reset_device(urb->dev); | |
194 | if (ret < 0) | |
195 | dev_err(&urb->dev->dev, "device reset\n"); | |
196 | ||
197 | usb_unlock_device(urb->dev); | |
198 | ||
199 | return ret; | |
200 | } | |
201 | ||
202 | /* | |
203 | * clear_halt, set_interface, and set_configuration require special tricks. | |
204 | */ | |
205 | static void tweak_special_requests(struct urb *urb) | |
206 | { | |
207 | if (!urb || !urb->setup_packet) | |
208 | return; | |
209 | ||
210 | if (usb_pipetype(urb->pipe) != PIPE_CONTROL) | |
211 | return; | |
212 | ||
213 | if (is_clear_halt_cmd(urb)) | |
214 | /* tweak clear_halt */ | |
215 | tweak_clear_halt_cmd(urb); | |
216 | ||
217 | else if (is_set_interface_cmd(urb)) | |
218 | /* tweak set_interface */ | |
219 | tweak_set_interface_cmd(urb); | |
220 | ||
221 | else if (is_set_configuration_cmd(urb)) | |
222 | /* tweak set_configuration */ | |
223 | tweak_set_configuration_cmd(urb); | |
224 | ||
225 | else if (is_reset_device_cmd(urb)) | |
226 | tweak_reset_device_cmd(urb); | |
227 | else | |
b8868e45 | 228 | usbip_dbg_stub_rx("no need to tweak\n"); |
4d7b5c7f TH |
229 | } |
230 | ||
231 | /* | |
232 | * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb(). | |
233 | * By unlinking the urb asynchronously, stub_rx can continuously | |
234 | * process coming urbs. Even if the urb is unlinked, its completion | |
235 | * handler will be called and stub_tx will send a return pdu. | |
236 | * | |
237 | * See also comments about unlinking strategy in vhci_hcd.c. | |
238 | */ | |
239 | static int stub_recv_cmd_unlink(struct stub_device *sdev, | |
240 | struct usbip_header *pdu) | |
241 | { | |
4d7b5c7f TH |
242 | unsigned long flags; |
243 | ||
244 | struct stub_priv *priv; | |
245 | ||
246 | ||
247 | spin_lock_irqsave(&sdev->priv_lock, flags); | |
248 | ||
88a1e909 | 249 | list_for_each_entry(priv, &sdev->priv_init, list) { |
4d7b5c7f TH |
250 | if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { |
251 | int ret; | |
252 | ||
253 | dev_info(&priv->urb->dev->dev, "unlink urb %p\n", | |
254 | priv->urb); | |
255 | ||
256 | /* | |
257 | * This matched urb is not completed yet (i.e., be in | |
258 | * flight in usb hcd hardware/driver). Now we are | |
259 | * cancelling it. The unlinking flag means that we are | |
260 | * now not going to return the normal result pdu of a | |
261 | * submission request, but going to return a result pdu | |
262 | * of the unlink request. | |
263 | */ | |
264 | priv->unlinking = 1; | |
265 | ||
266 | /* | |
267 | * In the case that unlinking flag is on, prev->seqnum | |
268 | * is changed from the seqnum of the cancelling urb to | |
269 | * the seqnum of the unlink request. This will be used | |
270 | * to make the result pdu of the unlink request. | |
271 | */ | |
272 | priv->seqnum = pdu->base.seqnum; | |
273 | ||
274 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | |
275 | ||
276 | /* | |
277 | * usb_unlink_urb() is now out of spinlocking to avoid | |
278 | * spinlock recursion since stub_complete() is | |
279 | * sometimes called in this context but not in the | |
280 | * interrupt context. If stub_complete() is executed | |
281 | * before we call usb_unlink_urb(), usb_unlink_urb() | |
282 | * will return an error value. In this case, stub_tx | |
283 | * will return the result pdu of this unlink request | |
284 | * though submission is completed and actual unlinking | |
285 | * is not executed. OK? | |
286 | */ | |
287 | /* In the above case, urb->status is not -ECONNRESET, | |
288 | * so a driver in a client host will know the failure | |
289 | * of the unlink request ? | |
290 | */ | |
291 | ret = usb_unlink_urb(priv->urb); | |
292 | if (ret != -EINPROGRESS) | |
293 | dev_err(&priv->urb->dev->dev, | |
294 | "failed to unlink a urb %p, ret %d\n", | |
295 | priv->urb, ret); | |
296 | return 0; | |
297 | } | |
298 | } | |
299 | ||
b8868e45 BM |
300 | usbip_dbg_stub_rx("seqnum %d is not pending\n", |
301 | pdu->u.cmd_unlink.seqnum); | |
4d7b5c7f TH |
302 | |
303 | /* | |
304 | * The urb of the unlink target is not found in priv_init queue. It was | |
305 | * already completed and its results is/was going to be sent by a | |
306 | * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only | |
307 | * return the completeness of this unlink request to vhci_hcd. | |
308 | */ | |
309 | stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0); | |
310 | ||
311 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | |
312 | ||
313 | ||
314 | return 0; | |
315 | } | |
316 | ||
317 | static int valid_request(struct stub_device *sdev, struct usbip_header *pdu) | |
318 | { | |
319 | struct usbip_device *ud = &sdev->ud; | |
320 | ||
321 | if (pdu->base.devid == sdev->devid) { | |
322 | spin_lock(&ud->lock); | |
323 | if (ud->status == SDEV_ST_USED) { | |
324 | /* A request is valid. */ | |
325 | spin_unlock(&ud->lock); | |
326 | return 1; | |
327 | } | |
328 | spin_unlock(&ud->lock); | |
329 | } | |
330 | ||
331 | return 0; | |
332 | } | |
333 | ||
334 | static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, | |
335 | struct usbip_header *pdu) | |
336 | { | |
337 | struct stub_priv *priv; | |
338 | struct usbip_device *ud = &sdev->ud; | |
339 | unsigned long flags; | |
340 | ||
341 | spin_lock_irqsave(&sdev->priv_lock, flags); | |
342 | ||
e68f2849 | 343 | priv = kmem_cache_zalloc(stub_priv_cache, GFP_ATOMIC); |
4d7b5c7f TH |
344 | if (!priv) { |
345 | dev_err(&sdev->interface->dev, "alloc stub_priv\n"); | |
346 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | |
347 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | |
348 | return NULL; | |
349 | } | |
350 | ||
4d7b5c7f TH |
351 | priv->seqnum = pdu->base.seqnum; |
352 | priv->sdev = sdev; | |
353 | ||
354 | /* | |
355 | * After a stub_priv is linked to a list_head, | |
356 | * our error handler can free allocated data. | |
357 | */ | |
358 | list_add_tail(&priv->list, &sdev->priv_init); | |
359 | ||
360 | spin_unlock_irqrestore(&sdev->priv_lock, flags); | |
361 | ||
362 | return priv; | |
363 | } | |
364 | ||
4d7b5c7f TH |
365 | static int get_pipe(struct stub_device *sdev, int epnum, int dir) |
366 | { | |
367 | struct usb_device *udev = interface_to_usbdev(sdev->interface); | |
368 | struct usb_host_endpoint *ep; | |
369 | struct usb_endpoint_descriptor *epd = NULL; | |
370 | ||
ab30f12d EK |
371 | if (dir == USBIP_DIR_IN) |
372 | ep = udev->ep_in[epnum & 0x7f]; | |
373 | else | |
374 | ep = udev->ep_out[epnum & 0x7f]; | |
4d7b5c7f TH |
375 | if (!ep) { |
376 | dev_err(&sdev->interface->dev, "no such endpoint?, %d\n", | |
377 | epnum); | |
378 | BUG(); | |
379 | } | |
380 | ||
381 | epd = &ep->desc; | |
382 | ||
383 | ||
384 | #if 0 | |
385 | /* epnum 0 is always control */ | |
386 | if (epnum == 0) { | |
387 | if (dir == USBIP_DIR_OUT) | |
388 | return usb_sndctrlpipe(udev, 0); | |
389 | else | |
390 | return usb_rcvctrlpipe(udev, 0); | |
391 | } | |
392 | #endif | |
393 | ||
394 | if (usb_endpoint_xfer_control(epd)) { | |
395 | if (dir == USBIP_DIR_OUT) | |
396 | return usb_sndctrlpipe(udev, epnum); | |
397 | else | |
398 | return usb_rcvctrlpipe(udev, epnum); | |
399 | } | |
400 | ||
401 | if (usb_endpoint_xfer_bulk(epd)) { | |
402 | if (dir == USBIP_DIR_OUT) | |
403 | return usb_sndbulkpipe(udev, epnum); | |
404 | else | |
405 | return usb_rcvbulkpipe(udev, epnum); | |
406 | } | |
407 | ||
408 | if (usb_endpoint_xfer_int(epd)) { | |
409 | if (dir == USBIP_DIR_OUT) | |
410 | return usb_sndintpipe(udev, epnum); | |
411 | else | |
412 | return usb_rcvintpipe(udev, epnum); | |
413 | } | |
414 | ||
415 | if (usb_endpoint_xfer_isoc(epd)) { | |
416 | if (dir == USBIP_DIR_OUT) | |
417 | return usb_sndisocpipe(udev, epnum); | |
418 | else | |
419 | return usb_rcvisocpipe(udev, epnum); | |
420 | } | |
421 | ||
422 | /* NOT REACHED */ | |
423 | dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum); | |
424 | return 0; | |
425 | } | |
426 | ||
b7a937e9 EK |
427 | static void masking_bogus_flags(struct urb *urb) |
428 | { | |
429 | int xfertype; | |
430 | struct usb_device *dev; | |
431 | struct usb_host_endpoint *ep; | |
432 | int is_out; | |
433 | unsigned int allowed; | |
434 | ||
435 | if (!urb || urb->hcpriv || !urb->complete) | |
436 | return; | |
437 | dev = urb->dev; | |
438 | if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) | |
439 | return; | |
440 | ||
441 | ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out) | |
442 | [usb_pipeendpoint(urb->pipe)]; | |
443 | if (!ep) | |
444 | return; | |
445 | ||
446 | xfertype = usb_endpoint_type(&ep->desc); | |
447 | if (xfertype == USB_ENDPOINT_XFER_CONTROL) { | |
448 | struct usb_ctrlrequest *setup = | |
449 | (struct usb_ctrlrequest *) urb->setup_packet; | |
450 | ||
451 | if (!setup) | |
452 | return; | |
453 | is_out = !(setup->bRequestType & USB_DIR_IN) || | |
454 | !setup->wLength; | |
455 | } else { | |
456 | is_out = usb_endpoint_dir_out(&ep->desc); | |
457 | } | |
458 | ||
459 | /* enforce simple/standard policy */ | |
3924865f GKH |
460 | allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | |
461 | URB_DIR_MASK | URB_FREE_BUFFER); | |
b7a937e9 EK |
462 | switch (xfertype) { |
463 | case USB_ENDPOINT_XFER_BULK: | |
464 | if (is_out) | |
465 | allowed |= URB_ZERO_PACKET; | |
466 | /* FALLTHROUGH */ | |
467 | case USB_ENDPOINT_XFER_CONTROL: | |
468 | allowed |= URB_NO_FSBR; /* only affects UHCI */ | |
469 | /* FALLTHROUGH */ | |
470 | default: /* all non-iso endpoints */ | |
471 | if (!is_out) | |
472 | allowed |= URB_SHORT_NOT_OK; | |
473 | break; | |
474 | case USB_ENDPOINT_XFER_ISOC: | |
475 | allowed |= URB_ISO_ASAP; | |
476 | break; | |
477 | } | |
478 | urb->transfer_flags &= allowed; | |
479 | } | |
480 | ||
4d7b5c7f TH |
481 | static void stub_recv_cmd_submit(struct stub_device *sdev, |
482 | struct usbip_header *pdu) | |
483 | { | |
484 | int ret; | |
485 | struct stub_priv *priv; | |
486 | struct usbip_device *ud = &sdev->ud; | |
487 | struct usb_device *udev = interface_to_usbdev(sdev->interface); | |
488 | int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); | |
489 | ||
490 | ||
491 | priv = stub_priv_alloc(sdev, pdu); | |
492 | if (!priv) | |
493 | return; | |
494 | ||
495 | /* setup a urb */ | |
496 | if (usb_pipeisoc(pipe)) | |
497 | priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, | |
498 | GFP_KERNEL); | |
499 | else | |
500 | priv->urb = usb_alloc_urb(0, GFP_KERNEL); | |
501 | ||
502 | if (!priv->urb) { | |
503 | dev_err(&sdev->interface->dev, "malloc urb\n"); | |
504 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | |
505 | return; | |
506 | } | |
507 | ||
508 | /* set priv->urb->transfer_buffer */ | |
509 | if (pdu->u.cmd_submit.transfer_buffer_length > 0) { | |
510 | priv->urb->transfer_buffer = | |
511 | kzalloc(pdu->u.cmd_submit.transfer_buffer_length, | |
512 | GFP_KERNEL); | |
513 | if (!priv->urb->transfer_buffer) { | |
514 | dev_err(&sdev->interface->dev, "malloc x_buff\n"); | |
515 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | |
516 | return; | |
517 | } | |
518 | } | |
519 | ||
520 | /* set priv->urb->setup_packet */ | |
94002c07 JL |
521 | priv->urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8, |
522 | GFP_KERNEL); | |
4d7b5c7f TH |
523 | if (!priv->urb->setup_packet) { |
524 | dev_err(&sdev->interface->dev, "allocate setup_packet\n"); | |
525 | usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); | |
526 | return; | |
527 | } | |
4d7b5c7f TH |
528 | |
529 | /* set other members from the base header of pdu */ | |
530 | priv->urb->context = (void *) priv; | |
531 | priv->urb->dev = udev; | |
532 | priv->urb->pipe = pipe; | |
533 | priv->urb->complete = stub_complete; | |
534 | ||
535 | usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); | |
536 | ||
537 | ||
538 | if (usbip_recv_xbuff(ud, priv->urb) < 0) | |
539 | return; | |
540 | ||
541 | if (usbip_recv_iso(ud, priv->urb) < 0) | |
542 | return; | |
543 | ||
544 | /* no need to submit an intercepted request, but harmless? */ | |
545 | tweak_special_requests(priv->urb); | |
546 | ||
b7a937e9 | 547 | masking_bogus_flags(priv->urb); |
4d7b5c7f TH |
548 | /* urb is now ready to submit */ |
549 | ret = usb_submit_urb(priv->urb, GFP_KERNEL); | |
550 | ||
551 | if (ret == 0) | |
b8868e45 BM |
552 | usbip_dbg_stub_rx("submit urb ok, seqnum %u\n", |
553 | pdu->base.seqnum); | |
4d7b5c7f TH |
554 | else { |
555 | dev_err(&sdev->interface->dev, "submit_urb error, %d\n", ret); | |
556 | usbip_dump_header(pdu); | |
557 | usbip_dump_urb(priv->urb); | |
558 | ||
559 | /* | |
560 | * Pessimistic. | |
561 | * This connection will be discarded. | |
562 | */ | |
563 | usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); | |
564 | } | |
565 | ||
b8868e45 | 566 | usbip_dbg_stub_rx("Leave\n"); |
4d7b5c7f TH |
567 | return; |
568 | } | |
569 | ||
570 | /* recv a pdu */ | |
571 | static void stub_rx_pdu(struct usbip_device *ud) | |
572 | { | |
573 | int ret; | |
574 | struct usbip_header pdu; | |
575 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | |
576 | struct device *dev = &sdev->interface->dev; | |
577 | ||
b8868e45 | 578 | usbip_dbg_stub_rx("Enter\n"); |
4d7b5c7f TH |
579 | |
580 | memset(&pdu, 0, sizeof(pdu)); | |
581 | ||
582 | /* 1. receive a pdu header */ | |
583 | ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0); | |
584 | if (ret != sizeof(pdu)) { | |
585 | dev_err(dev, "recv a header, %d\n", ret); | |
586 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
587 | return; | |
588 | } | |
589 | ||
590 | usbip_header_correct_endian(&pdu, 0); | |
591 | ||
b8868e45 | 592 | if (usbip_dbg_flag_stub_rx) |
4d7b5c7f TH |
593 | usbip_dump_header(&pdu); |
594 | ||
595 | if (!valid_request(sdev, &pdu)) { | |
596 | dev_err(dev, "recv invalid request\n"); | |
597 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
598 | return; | |
599 | } | |
600 | ||
601 | switch (pdu.base.command) { | |
602 | case USBIP_CMD_UNLINK: | |
603 | stub_recv_cmd_unlink(sdev, &pdu); | |
604 | break; | |
605 | ||
606 | case USBIP_CMD_SUBMIT: | |
607 | stub_recv_cmd_submit(sdev, &pdu); | |
608 | break; | |
609 | ||
610 | default: | |
611 | /* NOTREACHED */ | |
612 | dev_err(dev, "unknown pdu\n"); | |
613 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
614 | return; | |
615 | } | |
616 | ||
617 | } | |
618 | ||
619 | void stub_rx_loop(struct usbip_task *ut) | |
620 | { | |
621 | struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); | |
622 | ||
623 | while (1) { | |
624 | if (signal_pending(current)) { | |
b8868e45 | 625 | usbip_dbg_stub_rx("signal caught!\n"); |
4d7b5c7f TH |
626 | break; |
627 | } | |
628 | ||
b8868e45 | 629 | if (usbip_event_happened(ud)) |
4d7b5c7f TH |
630 | break; |
631 | ||
632 | stub_rx_pdu(ud); | |
633 | } | |
634 | } |