]>
Commit | Line | Data |
---|---|---|
05a1f28e 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 | ||
7aaacb43 | 20 | #include <asm/byteorder.h> |
05a1f28e | 21 | #include <linux/file.h> |
7aaacb43 | 22 | #include <linux/fs.h> |
23 | #include <linux/kernel.h> | |
5a0e3ad6 | 24 | #include <linux/slab.h> |
93efc55b | 25 | #include <linux/stat.h> |
45296236 | 26 | #include <linux/module.h> |
93efc55b | 27 | #include <linux/moduleparam.h> |
7aaacb43 | 28 | #include <net/sock.h> |
4ce0a41f | 29 | |
05a1f28e TH |
30 | #include "usbip_common.h" |
31 | ||
4ce0a41f | 32 | #define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>" |
64e62426 | 33 | #define DRIVER_DESC "USB/IP Core" |
05a1f28e | 34 | |
64e62426 | 35 | #ifdef CONFIG_USBIP_DEBUG |
05a1f28e TH |
36 | unsigned long usbip_debug_flag = 0xffffffff; |
37 | #else | |
38 | unsigned long usbip_debug_flag; | |
39 | #endif | |
40 | EXPORT_SYMBOL_GPL(usbip_debug_flag); | |
93efc55b TK |
41 | module_param(usbip_debug_flag, ulong, S_IRUGO|S_IWUSR); |
42 | MODULE_PARM_DESC(usbip_debug_flag, "debug flags (defined in usbip_common.h)"); | |
05a1f28e | 43 | |
05a1f28e TH |
44 | /* FIXME */ |
45 | struct device_attribute dev_attr_usbip_debug; | |
46 | EXPORT_SYMBOL_GPL(dev_attr_usbip_debug); | |
47 | ||
b1f56aca GKH |
48 | static ssize_t usbip_debug_show(struct device *dev, |
49 | struct device_attribute *attr, char *buf) | |
05a1f28e TH |
50 | { |
51 | return sprintf(buf, "%lx\n", usbip_debug_flag); | |
52 | } | |
53 | ||
b1f56aca GKH |
54 | static ssize_t usbip_debug_store(struct device *dev, |
55 | struct device_attribute *attr, const char *buf, | |
56 | size_t count) | |
05a1f28e | 57 | { |
bf988c16 JG |
58 | if (sscanf(buf, "%lx", &usbip_debug_flag) != 1) |
59 | return -EINVAL; | |
05a1f28e TH |
60 | return count; |
61 | } | |
b1f56aca | 62 | DEVICE_ATTR_RW(usbip_debug); |
05a1f28e TH |
63 | |
64 | static void usbip_dump_buffer(char *buff, int bufflen) | |
65 | { | |
1a4b6f66 | 66 | print_hex_dump(KERN_DEBUG, "usbip-core", DUMP_PREFIX_OFFSET, 16, 4, |
aad86577 | 67 | buff, bufflen, false); |
05a1f28e TH |
68 | } |
69 | ||
70 | static void usbip_dump_pipe(unsigned int p) | |
71 | { | |
72 | unsigned char type = usb_pipetype(p); | |
87352760 | 73 | unsigned char ep = usb_pipeendpoint(p); |
74 | unsigned char dev = usb_pipedevice(p); | |
75 | unsigned char dir = usb_pipein(p); | |
05a1f28e | 76 | |
1a4b6f66 | 77 | pr_debug("dev(%d) ep(%d) [%s] ", dev, ep, dir ? "IN" : "OUT"); |
05a1f28e TH |
78 | |
79 | switch (type) { | |
80 | case PIPE_ISOCHRONOUS: | |
1a4b6f66 | 81 | pr_debug("ISO\n"); |
05a1f28e TH |
82 | break; |
83 | case PIPE_INTERRUPT: | |
1a4b6f66 | 84 | pr_debug("INT\n"); |
05a1f28e TH |
85 | break; |
86 | case PIPE_CONTROL: | |
1a4b6f66 | 87 | pr_debug("CTRL\n"); |
05a1f28e TH |
88 | break; |
89 | case PIPE_BULK: | |
1a4b6f66 | 90 | pr_debug("BULK\n"); |
05a1f28e TH |
91 | break; |
92 | default: | |
1a4b6f66 | 93 | pr_debug("ERR\n"); |
49aecefc | 94 | break; |
05a1f28e | 95 | } |
05a1f28e TH |
96 | } |
97 | ||
98 | static void usbip_dump_usb_device(struct usb_device *udev) | |
99 | { | |
100 | struct device *dev = &udev->dev; | |
101 | int i; | |
102 | ||
09c8c8fb SK |
103 | dev_dbg(dev, " devnum(%d) devpath(%s) usb speed(%s)", |
104 | udev->devnum, udev->devpath, usb_speed_string(udev->speed)); | |
05a1f28e | 105 | |
1a4b6f66 | 106 | pr_debug("tt %p, ttport %d\n", udev->tt, udev->ttport); |
05a1f28e TH |
107 | |
108 | dev_dbg(dev, " "); | |
109 | for (i = 0; i < 16; i++) | |
1a4b6f66 | 110 | pr_debug(" %2u", i); |
111 | pr_debug("\n"); | |
05a1f28e TH |
112 | |
113 | dev_dbg(dev, " toggle0(IN) :"); | |
114 | for (i = 0; i < 16; i++) | |
1a4b6f66 | 115 | pr_debug(" %2u", (udev->toggle[0] & (1 << i)) ? 1 : 0); |
116 | pr_debug("\n"); | |
05a1f28e TH |
117 | |
118 | dev_dbg(dev, " toggle1(OUT):"); | |
119 | for (i = 0; i < 16; i++) | |
1a4b6f66 | 120 | pr_debug(" %2u", (udev->toggle[1] & (1 << i)) ? 1 : 0); |
121 | pr_debug("\n"); | |
05a1f28e TH |
122 | |
123 | dev_dbg(dev, " epmaxp_in :"); | |
124 | for (i = 0; i < 16; i++) { | |
125 | if (udev->ep_in[i]) | |
1a4b6f66 | 126 | pr_debug(" %2u", |
127 | le16_to_cpu(udev->ep_in[i]->desc.wMaxPacketSize)); | |
05a1f28e | 128 | } |
1a4b6f66 | 129 | pr_debug("\n"); |
05a1f28e TH |
130 | |
131 | dev_dbg(dev, " epmaxp_out :"); | |
132 | for (i = 0; i < 16; i++) { | |
133 | if (udev->ep_out[i]) | |
1a4b6f66 | 134 | pr_debug(" %2u", |
135 | le16_to_cpu(udev->ep_out[i]->desc.wMaxPacketSize)); | |
05a1f28e | 136 | } |
1a4b6f66 | 137 | pr_debug("\n"); |
05a1f28e TH |
138 | |
139 | dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus); | |
140 | ||
b482da2b HS |
141 | dev_dbg(dev, |
142 | "descriptor %p, config %p, actconfig %p, rawdescriptors %p\n", | |
143 | &udev->descriptor, udev->config, | |
05a1f28e TH |
144 | udev->actconfig, udev->rawdescriptors); |
145 | ||
146 | dev_dbg(dev, "have_langid %d, string_langid %d\n", | |
147 | udev->have_langid, udev->string_langid); | |
148 | ||
ff823c79 | 149 | dev_dbg(dev, "maxchild %d\n", udev->maxchild); |
05a1f28e TH |
150 | } |
151 | ||
152 | static void usbip_dump_request_type(__u8 rt) | |
153 | { | |
154 | switch (rt & USB_RECIP_MASK) { | |
155 | case USB_RECIP_DEVICE: | |
1a4b6f66 | 156 | pr_debug("DEVICE"); |
05a1f28e TH |
157 | break; |
158 | case USB_RECIP_INTERFACE: | |
1a4b6f66 | 159 | pr_debug("INTERF"); |
05a1f28e TH |
160 | break; |
161 | case USB_RECIP_ENDPOINT: | |
1a4b6f66 | 162 | pr_debug("ENDPOI"); |
05a1f28e TH |
163 | break; |
164 | case USB_RECIP_OTHER: | |
1a4b6f66 | 165 | pr_debug("OTHER "); |
05a1f28e TH |
166 | break; |
167 | default: | |
1a4b6f66 | 168 | pr_debug("------"); |
49aecefc | 169 | break; |
05a1f28e TH |
170 | } |
171 | } | |
172 | ||
173 | static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd) | |
174 | { | |
175 | if (!cmd) { | |
1a4b6f66 | 176 | pr_debug(" : null pointer\n"); |
05a1f28e TH |
177 | return; |
178 | } | |
179 | ||
1a4b6f66 | 180 | pr_debug(" "); |
6bb3ee69 CC |
181 | pr_debug("bRequestType(%02X) bRequest(%02X) wValue(%04X) wIndex(%04X) wLength(%04X) ", |
182 | cmd->bRequestType, cmd->bRequest, | |
1a4b6f66 | 183 | cmd->wValue, cmd->wIndex, cmd->wLength); |
184 | pr_debug("\n "); | |
05a1f28e TH |
185 | |
186 | if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { | |
1a4b6f66 | 187 | pr_debug("STANDARD "); |
05a1f28e TH |
188 | switch (cmd->bRequest) { |
189 | case USB_REQ_GET_STATUS: | |
1a4b6f66 | 190 | pr_debug("GET_STATUS\n"); |
05a1f28e TH |
191 | break; |
192 | case USB_REQ_CLEAR_FEATURE: | |
1a4b6f66 | 193 | pr_debug("CLEAR_FEAT\n"); |
05a1f28e TH |
194 | break; |
195 | case USB_REQ_SET_FEATURE: | |
5ad7b85b | 196 | pr_debug("SET_FEAT\n"); |
05a1f28e TH |
197 | break; |
198 | case USB_REQ_SET_ADDRESS: | |
1a4b6f66 | 199 | pr_debug("SET_ADDRRS\n"); |
05a1f28e TH |
200 | break; |
201 | case USB_REQ_GET_DESCRIPTOR: | |
1a4b6f66 | 202 | pr_debug("GET_DESCRI\n"); |
05a1f28e TH |
203 | break; |
204 | case USB_REQ_SET_DESCRIPTOR: | |
1a4b6f66 | 205 | pr_debug("SET_DESCRI\n"); |
05a1f28e TH |
206 | break; |
207 | case USB_REQ_GET_CONFIGURATION: | |
1a4b6f66 | 208 | pr_debug("GET_CONFIG\n"); |
05a1f28e TH |
209 | break; |
210 | case USB_REQ_SET_CONFIGURATION: | |
1a4b6f66 | 211 | pr_debug("SET_CONFIG\n"); |
05a1f28e TH |
212 | break; |
213 | case USB_REQ_GET_INTERFACE: | |
1a4b6f66 | 214 | pr_debug("GET_INTERF\n"); |
05a1f28e TH |
215 | break; |
216 | case USB_REQ_SET_INTERFACE: | |
1a4b6f66 | 217 | pr_debug("SET_INTERF\n"); |
05a1f28e TH |
218 | break; |
219 | case USB_REQ_SYNCH_FRAME: | |
1a4b6f66 | 220 | pr_debug("SYNC_FRAME\n"); |
05a1f28e TH |
221 | break; |
222 | default: | |
5ad7b85b | 223 | pr_debug("REQ(%02X)\n", cmd->bRequest); |
49aecefc | 224 | break; |
05a1f28e | 225 | } |
05a1f28e | 226 | usbip_dump_request_type(cmd->bRequestType); |
1a4b6f66 | 227 | } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) { |
5ad7b85b | 228 | pr_debug("CLASS\n"); |
1a4b6f66 | 229 | } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) { |
5ad7b85b | 230 | pr_debug("VENDOR\n"); |
1a4b6f66 | 231 | } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) { |
232 | pr_debug("RESERVED\n"); | |
233 | } | |
05a1f28e TH |
234 | } |
235 | ||
236 | void usbip_dump_urb(struct urb *urb) | |
237 | { | |
238 | struct device *dev; | |
239 | ||
240 | if (!urb) { | |
1a4b6f66 | 241 | pr_debug("urb: null pointer!!\n"); |
05a1f28e TH |
242 | return; |
243 | } | |
244 | ||
245 | if (!urb->dev) { | |
1a4b6f66 | 246 | pr_debug("urb->dev: null pointer!!\n"); |
05a1f28e TH |
247 | return; |
248 | } | |
1a4b6f66 | 249 | |
05a1f28e TH |
250 | dev = &urb->dev->dev; |
251 | ||
252 | dev_dbg(dev, " urb :%p\n", urb); | |
253 | dev_dbg(dev, " dev :%p\n", urb->dev); | |
254 | ||
255 | usbip_dump_usb_device(urb->dev); | |
256 | ||
257 | dev_dbg(dev, " pipe :%08x ", urb->pipe); | |
258 | ||
259 | usbip_dump_pipe(urb->pipe); | |
260 | ||
261 | dev_dbg(dev, " status :%d\n", urb->status); | |
262 | dev_dbg(dev, " transfer_flags :%08X\n", urb->transfer_flags); | |
263 | dev_dbg(dev, " transfer_buffer :%p\n", urb->transfer_buffer); | |
b8868e45 BM |
264 | dev_dbg(dev, " transfer_buffer_length:%d\n", |
265 | urb->transfer_buffer_length); | |
05a1f28e TH |
266 | dev_dbg(dev, " actual_length :%d\n", urb->actual_length); |
267 | dev_dbg(dev, " setup_packet :%p\n", urb->setup_packet); | |
268 | ||
269 | if (urb->setup_packet && usb_pipetype(urb->pipe) == PIPE_CONTROL) | |
f9eacc98 | 270 | usbip_dump_usb_ctrlrequest( |
05a1f28e TH |
271 | (struct usb_ctrlrequest *)urb->setup_packet); |
272 | ||
273 | dev_dbg(dev, " start_frame :%d\n", urb->start_frame); | |
274 | dev_dbg(dev, " number_of_packets :%d\n", urb->number_of_packets); | |
275 | dev_dbg(dev, " interval :%d\n", urb->interval); | |
276 | dev_dbg(dev, " error_count :%d\n", urb->error_count); | |
277 | dev_dbg(dev, " context :%p\n", urb->context); | |
278 | dev_dbg(dev, " complete :%p\n", urb->complete); | |
279 | } | |
280 | EXPORT_SYMBOL_GPL(usbip_dump_urb); | |
281 | ||
282 | void usbip_dump_header(struct usbip_header *pdu) | |
283 | { | |
1a4b6f66 | 284 | pr_debug("BASE: cmd %u seq %u devid %u dir %u ep %u\n", |
285 | pdu->base.command, | |
286 | pdu->base.seqnum, | |
287 | pdu->base.devid, | |
288 | pdu->base.direction, | |
289 | pdu->base.ep); | |
05a1f28e TH |
290 | |
291 | switch (pdu->base.command) { | |
292 | case USBIP_CMD_SUBMIT: | |
6bb3ee69 | 293 | pr_debug("USBIP_CMD_SUBMIT: x_flags %u x_len %u sf %u #p %d iv %d\n", |
1a4b6f66 | 294 | pdu->u.cmd_submit.transfer_flags, |
295 | pdu->u.cmd_submit.transfer_buffer_length, | |
296 | pdu->u.cmd_submit.start_frame, | |
297 | pdu->u.cmd_submit.number_of_packets, | |
298 | pdu->u.cmd_submit.interval); | |
f9eacc98 | 299 | break; |
05a1f28e | 300 | case USBIP_CMD_UNLINK: |
1a4b6f66 | 301 | pr_debug("USBIP_CMD_UNLINK: seq %u\n", |
302 | pdu->u.cmd_unlink.seqnum); | |
05a1f28e TH |
303 | break; |
304 | case USBIP_RET_SUBMIT: | |
1a4b6f66 | 305 | pr_debug("USBIP_RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n", |
306 | pdu->u.ret_submit.status, | |
307 | pdu->u.ret_submit.actual_length, | |
308 | pdu->u.ret_submit.start_frame, | |
309 | pdu->u.ret_submit.number_of_packets, | |
310 | pdu->u.ret_submit.error_count); | |
311 | break; | |
05a1f28e | 312 | case USBIP_RET_UNLINK: |
1a4b6f66 | 313 | pr_debug("USBIP_RET_UNLINK: status %d\n", |
314 | pdu->u.ret_unlink.status); | |
05a1f28e TH |
315 | break; |
316 | default: | |
317 | /* NOT REACHED */ | |
1a4b6f66 | 318 | pr_err("unknown command\n"); |
49aecefc | 319 | break; |
05a1f28e TH |
320 | } |
321 | } | |
322 | EXPORT_SYMBOL_GPL(usbip_dump_header); | |
323 | ||
5a08c526 BW |
324 | /* Receive data over TCP/IP. */ |
325 | int usbip_recv(struct socket *sock, void *buf, int size) | |
05a1f28e TH |
326 | { |
327 | int result; | |
328 | struct msghdr msg; | |
329 | struct kvec iov; | |
330 | int total = 0; | |
331 | ||
b8868e45 | 332 | /* for blocks of if (usbip_dbg_flag_xmit) */ |
05a1f28e TH |
333 | char *bp = buf; |
334 | int osize = size; | |
335 | ||
b8868e45 | 336 | usbip_dbg_xmit("enter\n"); |
05a1f28e TH |
337 | |
338 | if (!sock || !buf || !size) { | |
1a4b6f66 | 339 | pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf, |
340 | size); | |
05a1f28e TH |
341 | return -EINVAL; |
342 | } | |
343 | ||
05a1f28e TH |
344 | do { |
345 | sock->sk->sk_allocation = GFP_NOIO; | |
346 | iov.iov_base = buf; | |
347 | iov.iov_len = size; | |
348 | msg.msg_name = NULL; | |
349 | msg.msg_namelen = 0; | |
350 | msg.msg_control = NULL; | |
351 | msg.msg_controllen = 0; | |
5a08c526 | 352 | msg.msg_flags = MSG_NOSIGNAL; |
05a1f28e | 353 | |
5a08c526 | 354 | result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); |
05a1f28e | 355 | if (result <= 0) { |
5a08c526 BW |
356 | pr_debug("receive sock %p buf %p size %u ret %d total %d\n", |
357 | sock, buf, size, result, total); | |
05a1f28e TH |
358 | goto err; |
359 | } | |
360 | ||
361 | size -= result; | |
362 | buf += result; | |
363 | total += result; | |
05a1f28e TH |
364 | } while (size > 0); |
365 | ||
b8868e45 | 366 | if (usbip_dbg_flag_xmit) { |
5a08c526 BW |
367 | if (!in_interrupt()) |
368 | pr_debug("%-10s:", current->comm); | |
369 | else | |
370 | pr_debug("interrupt :"); | |
05a1f28e | 371 | |
5a08c526 BW |
372 | pr_debug("receiving....\n"); |
373 | usbip_dump_buffer(bp, osize); | |
374 | pr_debug("received, osize %d ret %d size %d total %d\n", | |
ca9fb17e | 375 | osize, result, size, total); |
05a1f28e TH |
376 | } |
377 | ||
378 | return total; | |
379 | ||
380 | err: | |
381 | return result; | |
382 | } | |
5a08c526 | 383 | EXPORT_SYMBOL_GPL(usbip_recv); |
05a1f28e | 384 | |
05a1f28e TH |
385 | /* there may be more cases to tweak the flags. */ |
386 | static unsigned int tweak_transfer_flags(unsigned int flags) | |
387 | { | |
85bcb5ee | 388 | flags &= ~URB_NO_TRANSFER_DMA_MAP; |
05a1f28e TH |
389 | return flags; |
390 | } | |
391 | ||
392 | static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, | |
f9eacc98 | 393 | int pack) |
05a1f28e TH |
394 | { |
395 | struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit; | |
396 | ||
397 | /* | |
398 | * Some members are not still implemented in usbip. I hope this issue | |
399 | * will be discussed when usbip is ported to other operating systems. | |
400 | */ | |
401 | if (pack) { | |
05a1f28e | 402 | spdu->transfer_flags = |
f9eacc98 | 403 | tweak_transfer_flags(urb->transfer_flags); |
05a1f28e TH |
404 | spdu->transfer_buffer_length = urb->transfer_buffer_length; |
405 | spdu->start_frame = urb->start_frame; | |
406 | spdu->number_of_packets = urb->number_of_packets; | |
407 | spdu->interval = urb->interval; | |
408 | } else { | |
05a1f28e | 409 | urb->transfer_flags = spdu->transfer_flags; |
05a1f28e TH |
410 | urb->transfer_buffer_length = spdu->transfer_buffer_length; |
411 | urb->start_frame = spdu->start_frame; | |
412 | urb->number_of_packets = spdu->number_of_packets; | |
413 | urb->interval = spdu->interval; | |
414 | } | |
415 | } | |
416 | ||
417 | static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, | |
f9eacc98 | 418 | int pack) |
05a1f28e TH |
419 | { |
420 | struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit; | |
421 | ||
422 | if (pack) { | |
05a1f28e TH |
423 | rpdu->status = urb->status; |
424 | rpdu->actual_length = urb->actual_length; | |
425 | rpdu->start_frame = urb->start_frame; | |
1325f85f | 426 | rpdu->number_of_packets = urb->number_of_packets; |
05a1f28e TH |
427 | rpdu->error_count = urb->error_count; |
428 | } else { | |
05a1f28e TH |
429 | urb->status = rpdu->status; |
430 | urb->actual_length = rpdu->actual_length; | |
431 | urb->start_frame = rpdu->start_frame; | |
1325f85f | 432 | urb->number_of_packets = rpdu->number_of_packets; |
05a1f28e TH |
433 | urb->error_count = rpdu->error_count; |
434 | } | |
435 | } | |
436 | ||
05a1f28e | 437 | void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, |
f9eacc98 | 438 | int pack) |
05a1f28e TH |
439 | { |
440 | switch (cmd) { | |
441 | case USBIP_CMD_SUBMIT: | |
442 | usbip_pack_cmd_submit(pdu, urb, pack); | |
443 | break; | |
444 | case USBIP_RET_SUBMIT: | |
445 | usbip_pack_ret_submit(pdu, urb, pack); | |
446 | break; | |
447 | default: | |
49aecefc | 448 | /* NOT REACHED */ |
1a4b6f66 | 449 | pr_err("unknown command\n"); |
49aecefc | 450 | break; |
05a1f28e TH |
451 | } |
452 | } | |
453 | EXPORT_SYMBOL_GPL(usbip_pack_pdu); | |
454 | ||
05a1f28e TH |
455 | static void correct_endian_basic(struct usbip_header_basic *base, int send) |
456 | { | |
457 | if (send) { | |
458 | base->command = cpu_to_be32(base->command); | |
459 | base->seqnum = cpu_to_be32(base->seqnum); | |
460 | base->devid = cpu_to_be32(base->devid); | |
461 | base->direction = cpu_to_be32(base->direction); | |
462 | base->ep = cpu_to_be32(base->ep); | |
463 | } else { | |
464 | base->command = be32_to_cpu(base->command); | |
465 | base->seqnum = be32_to_cpu(base->seqnum); | |
466 | base->devid = be32_to_cpu(base->devid); | |
467 | base->direction = be32_to_cpu(base->direction); | |
468 | base->ep = be32_to_cpu(base->ep); | |
469 | } | |
470 | } | |
471 | ||
472 | static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, | |
f9eacc98 | 473 | int send) |
05a1f28e TH |
474 | { |
475 | if (send) { | |
476 | pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags); | |
477 | ||
478 | cpu_to_be32s(&pdu->transfer_buffer_length); | |
479 | cpu_to_be32s(&pdu->start_frame); | |
480 | cpu_to_be32s(&pdu->number_of_packets); | |
481 | cpu_to_be32s(&pdu->interval); | |
482 | } else { | |
483 | pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags); | |
484 | ||
485 | be32_to_cpus(&pdu->transfer_buffer_length); | |
486 | be32_to_cpus(&pdu->start_frame); | |
487 | be32_to_cpus(&pdu->number_of_packets); | |
488 | be32_to_cpus(&pdu->interval); | |
489 | } | |
490 | } | |
491 | ||
492 | static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, | |
f9eacc98 | 493 | int send) |
05a1f28e TH |
494 | { |
495 | if (send) { | |
496 | cpu_to_be32s(&pdu->status); | |
497 | cpu_to_be32s(&pdu->actual_length); | |
498 | cpu_to_be32s(&pdu->start_frame); | |
1325f85f | 499 | cpu_to_be32s(&pdu->number_of_packets); |
05a1f28e TH |
500 | cpu_to_be32s(&pdu->error_count); |
501 | } else { | |
502 | be32_to_cpus(&pdu->status); | |
503 | be32_to_cpus(&pdu->actual_length); | |
504 | be32_to_cpus(&pdu->start_frame); | |
cacd18a8 | 505 | be32_to_cpus(&pdu->number_of_packets); |
05a1f28e TH |
506 | be32_to_cpus(&pdu->error_count); |
507 | } | |
508 | } | |
509 | ||
510 | static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, | |
f9eacc98 | 511 | int send) |
05a1f28e TH |
512 | { |
513 | if (send) | |
514 | pdu->seqnum = cpu_to_be32(pdu->seqnum); | |
515 | else | |
516 | pdu->seqnum = be32_to_cpu(pdu->seqnum); | |
517 | } | |
518 | ||
519 | static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, | |
f9eacc98 | 520 | int send) |
05a1f28e TH |
521 | { |
522 | if (send) | |
523 | cpu_to_be32s(&pdu->status); | |
524 | else | |
525 | be32_to_cpus(&pdu->status); | |
526 | } | |
527 | ||
528 | void usbip_header_correct_endian(struct usbip_header *pdu, int send) | |
529 | { | |
530 | __u32 cmd = 0; | |
531 | ||
532 | if (send) | |
533 | cmd = pdu->base.command; | |
534 | ||
535 | correct_endian_basic(&pdu->base, send); | |
536 | ||
537 | if (!send) | |
538 | cmd = pdu->base.command; | |
539 | ||
540 | switch (cmd) { | |
541 | case USBIP_CMD_SUBMIT: | |
542 | correct_endian_cmd_submit(&pdu->u.cmd_submit, send); | |
543 | break; | |
544 | case USBIP_RET_SUBMIT: | |
545 | correct_endian_ret_submit(&pdu->u.ret_submit, send); | |
546 | break; | |
547 | case USBIP_CMD_UNLINK: | |
548 | correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send); | |
549 | break; | |
550 | case USBIP_RET_UNLINK: | |
551 | correct_endian_ret_unlink(&pdu->u.ret_unlink, send); | |
552 | break; | |
553 | default: | |
49aecefc | 554 | /* NOT REACHED */ |
1a4b6f66 | 555 | pr_err("unknown command\n"); |
49aecefc | 556 | break; |
05a1f28e TH |
557 | } |
558 | } | |
559 | EXPORT_SYMBOL_GPL(usbip_header_correct_endian); | |
560 | ||
2282e1fb | 561 | static void usbip_iso_packet_correct_endian( |
87352760 | 562 | struct usbip_iso_packet_descriptor *iso, int send) |
05a1f28e TH |
563 | { |
564 | /* does not need all members. but copy all simply. */ | |
565 | if (send) { | |
566 | iso->offset = cpu_to_be32(iso->offset); | |
567 | iso->length = cpu_to_be32(iso->length); | |
568 | iso->status = cpu_to_be32(iso->status); | |
569 | iso->actual_length = cpu_to_be32(iso->actual_length); | |
570 | } else { | |
571 | iso->offset = be32_to_cpu(iso->offset); | |
572 | iso->length = be32_to_cpu(iso->length); | |
573 | iso->status = be32_to_cpu(iso->status); | |
574 | iso->actual_length = be32_to_cpu(iso->actual_length); | |
575 | } | |
576 | } | |
577 | ||
578 | static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso, | |
f9eacc98 | 579 | struct usb_iso_packet_descriptor *uiso, int pack) |
05a1f28e TH |
580 | { |
581 | if (pack) { | |
582 | iso->offset = uiso->offset; | |
583 | iso->length = uiso->length; | |
584 | iso->status = uiso->status; | |
585 | iso->actual_length = uiso->actual_length; | |
586 | } else { | |
587 | uiso->offset = iso->offset; | |
588 | uiso->length = iso->length; | |
589 | uiso->status = iso->status; | |
590 | uiso->actual_length = iso->actual_length; | |
591 | } | |
592 | } | |
593 | ||
05a1f28e | 594 | /* must free buffer */ |
36ac9b05 BW |
595 | struct usbip_iso_packet_descriptor* |
596 | usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen) | |
05a1f28e | 597 | { |
05a1f28e TH |
598 | struct usbip_iso_packet_descriptor *iso; |
599 | int np = urb->number_of_packets; | |
600 | ssize_t size = np * sizeof(*iso); | |
601 | int i; | |
602 | ||
36ac9b05 BW |
603 | iso = kzalloc(size, GFP_KERNEL); |
604 | if (!iso) | |
05a1f28e TH |
605 | return NULL; |
606 | ||
607 | for (i = 0; i < np; i++) { | |
36ac9b05 BW |
608 | usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 1); |
609 | usbip_iso_packet_correct_endian(&iso[i], 1); | |
05a1f28e TH |
610 | } |
611 | ||
612 | *bufflen = size; | |
613 | ||
36ac9b05 | 614 | return iso; |
05a1f28e TH |
615 | } |
616 | EXPORT_SYMBOL_GPL(usbip_alloc_iso_desc_pdu); | |
617 | ||
618 | /* some members of urb must be substituted before. */ | |
619 | int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) | |
620 | { | |
621 | void *buff; | |
622 | struct usbip_iso_packet_descriptor *iso; | |
623 | int np = urb->number_of_packets; | |
624 | int size = np * sizeof(*iso); | |
625 | int i; | |
626 | int ret; | |
28276a28 | 627 | int total_length = 0; |
05a1f28e TH |
628 | |
629 | if (!usb_pipeisoc(urb->pipe)) | |
630 | return 0; | |
631 | ||
632 | /* my Bluetooth dongle gets ISO URBs which are np = 0 */ | |
f14287b9 | 633 | if (np == 0) |
05a1f28e | 634 | return 0; |
05a1f28e TH |
635 | |
636 | buff = kzalloc(size, GFP_KERNEL); | |
637 | if (!buff) | |
638 | return -ENOMEM; | |
639 | ||
5a08c526 | 640 | ret = usbip_recv(ud->tcp_socket, buff, size); |
05a1f28e TH |
641 | if (ret != size) { |
642 | dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n", | |
643 | ret); | |
644 | kfree(buff); | |
645 | ||
646 | if (ud->side == USBIP_STUB) | |
647 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
648 | else | |
649 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | |
650 | ||
651 | return -EPIPE; | |
652 | } | |
653 | ||
36ac9b05 | 654 | iso = (struct usbip_iso_packet_descriptor *) buff; |
05a1f28e | 655 | for (i = 0; i < np; i++) { |
36ac9b05 BW |
656 | usbip_iso_packet_correct_endian(&iso[i], 0); |
657 | usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 0); | |
28276a28 | 658 | total_length += urb->iso_frame_desc[i].actual_length; |
05a1f28e TH |
659 | } |
660 | ||
05a1f28e TH |
661 | kfree(buff); |
662 | ||
28276a28 AM |
663 | if (total_length != urb->actual_length) { |
664 | dev_err(&urb->dev->dev, | |
6bb3ee69 | 665 | "total length of iso packets %d not equal to actual length of buffer %d\n", |
f9eacc98 | 666 | total_length, urb->actual_length); |
28276a28 AM |
667 | |
668 | if (ud->side == USBIP_STUB) | |
669 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
670 | else | |
671 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | |
672 | ||
673 | return -EPIPE; | |
674 | } | |
675 | ||
05a1f28e TH |
676 | return ret; |
677 | } | |
678 | EXPORT_SYMBOL_GPL(usbip_recv_iso); | |
679 | ||
28276a28 AM |
680 | /* |
681 | * This functions restores the padding which was removed for optimizing | |
682 | * the bandwidth during transfer over tcp/ip | |
683 | * | |
684 | * buffer and iso packets need to be stored and be in propeper endian in urb | |
685 | * before calling this function | |
686 | */ | |
ac2b41ac | 687 | void usbip_pad_iso(struct usbip_device *ud, struct urb *urb) |
28276a28 AM |
688 | { |
689 | int np = urb->number_of_packets; | |
690 | int i; | |
28276a28 AM |
691 | int actualoffset = urb->actual_length; |
692 | ||
693 | if (!usb_pipeisoc(urb->pipe)) | |
ac2b41ac | 694 | return; |
28276a28 AM |
695 | |
696 | /* if no packets or length of data is 0, then nothing to unpack */ | |
697 | if (np == 0 || urb->actual_length == 0) | |
ac2b41ac | 698 | return; |
28276a28 AM |
699 | |
700 | /* | |
701 | * if actual_length is transfer_buffer_length then no padding is | |
702 | * present. | |
c7f00899 | 703 | */ |
28276a28 | 704 | if (urb->actual_length == urb->transfer_buffer_length) |
ac2b41ac | 705 | return; |
28276a28 AM |
706 | |
707 | /* | |
708 | * loop over all packets from last to first (to prevent overwritting | |
709 | * memory when padding) and move them into the proper place | |
710 | */ | |
711 | for (i = np-1; i > 0; i--) { | |
712 | actualoffset -= urb->iso_frame_desc[i].actual_length; | |
713 | memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset, | |
f9eacc98 | 714 | urb->transfer_buffer + actualoffset, |
715 | urb->iso_frame_desc[i].actual_length); | |
28276a28 | 716 | } |
28276a28 AM |
717 | } |
718 | EXPORT_SYMBOL_GPL(usbip_pad_iso); | |
05a1f28e TH |
719 | |
720 | /* some members of urb must be substituted before. */ | |
721 | int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) | |
722 | { | |
723 | int ret; | |
724 | int size; | |
725 | ||
726 | if (ud->side == USBIP_STUB) { | |
05a1f28e TH |
727 | /* the direction of urb must be OUT. */ |
728 | if (usb_pipein(urb->pipe)) | |
729 | return 0; | |
730 | ||
731 | size = urb->transfer_buffer_length; | |
732 | } else { | |
05a1f28e TH |
733 | /* the direction of urb must be IN. */ |
734 | if (usb_pipeout(urb->pipe)) | |
735 | return 0; | |
736 | ||
737 | size = urb->actual_length; | |
738 | } | |
739 | ||
740 | /* no need to recv xbuff */ | |
741 | if (!(size > 0)) | |
742 | return 0; | |
743 | ||
b348d7dd IK |
744 | if (size > urb->transfer_buffer_length) { |
745 | /* should not happen, probably malicious packet */ | |
746 | if (ud->side == USBIP_STUB) { | |
747 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
748 | return 0; | |
749 | } else { | |
750 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | |
751 | return -EPIPE; | |
752 | } | |
753 | } | |
754 | ||
5a08c526 | 755 | ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); |
05a1f28e TH |
756 | if (ret != size) { |
757 | dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); | |
758 | if (ud->side == USBIP_STUB) { | |
759 | usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); | |
760 | } else { | |
761 | usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); | |
762 | return -EPIPE; | |
763 | } | |
764 | } | |
765 | ||
766 | return ret; | |
767 | } | |
768 | EXPORT_SYMBOL_GPL(usbip_recv_xbuff); | |
769 | ||
3028d0ae | 770 | static int __init usbip_core_init(void) |
05a1f28e | 771 | { |
1a4b6f66 | 772 | pr_info(DRIVER_DESC " v" USBIP_VERSION "\n"); |
05a1f28e TH |
773 | return 0; |
774 | } | |
775 | ||
3028d0ae | 776 | static void __exit usbip_core_exit(void) |
05a1f28e TH |
777 | { |
778 | return; | |
779 | } | |
780 | ||
3028d0ae | 781 | module_init(usbip_core_init); |
782 | module_exit(usbip_core_exit); | |
05a1f28e TH |
783 | |
784 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
785 | MODULE_DESCRIPTION(DRIVER_DESC); | |
786 | MODULE_LICENSE("GPL"); | |
6973c6f2 | 787 | MODULE_VERSION(USBIP_VERSION); |