// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2003-2008 Takahiro Hirofuchi
* Copyright (C) 2015-2016 Samsung Electronics
* Krzysztof Opasiak <k.opasiak@samsung.com>
*/
#include <asm/byteorder.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <net/sock.h>
#include "usbip_common.h"
#define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>"
#define DRIVER_DESC "USB/IP Core"
#ifdef CONFIG_USBIP_DEBUG
unsigned long usbip_debug_flag = 0xffffffff;
#else
unsigned long usbip_debug_flag;
#endif
EXPORT_SYMBOL_GPL(usbip_debug_flag);
module_param(usbip_debug_flag, ulong, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(usbip_debug_flag, "debug flags (defined in usbip_common.h)");
/* FIXME */
struct device_attribute dev_attr_usbip_debug;
EXPORT_SYMBOL_GPL(dev_attr_usbip_debug);
static ssize_t usbip_debug_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%lx\n", usbip_debug_flag);
}
static ssize_t usbip_debug_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
if (sscanf(buf, "%lx", &usbip_debug_flag) != 1)
return -EINVAL;
return count;
}
DEVICE_ATTR_RW(usbip_debug);
static void usbip_dump_buffer(char *buff, int bufflen)
{
print_hex_dump(KERN_DEBUG, "usbip-core", DUMP_PREFIX_OFFSET, 16, 4,
buff, bufflen, false);
}
static void usbip_dump_pipe(unsigned int p)
{
unsigned char type = usb_pipetype(p);
unsigned char ep = usb_pipeendpoint(p);
unsigned char dev = usb_pipedevice(p);
unsigned char dir = usb_pipein(p);
pr_debug("dev(%d) ep(%d) [%s] ", dev, ep, dir ? "IN" : "OUT");
switch (type) {
case PIPE_ISOCHRONOUS:
pr_debug("ISO\n");
break;
case PIPE_INTERRUPT:
pr_debug("INT\n");
break;
case PIPE_CONTROL:
pr_debug("CTRL\n");
break;
case PIPE_BULK:
pr_debug("BULK\n");
break;
default:
pr_debug("ERR\n");
break;
}
}
static void usbip_dump_usb_device(struct usb_device *udev)
{
struct device *dev = &udev->dev;
int i;
dev_dbg(dev, " devnum(%d) devpath(%s) usb speed(%s)",
udev->devnum, udev->devpath, usb_speed_string(udev->speed));
pr_debug("tt hub ttport %d\n", udev->ttport);
dev_dbg(dev, " ");
for (i = 0; i < 16; i++)
pr_debug(" %2u", i);
pr_debug("\n");
dev_dbg(dev, " toggle0(IN) :");
for (i = 0; i < 16; i++)
pr_debug(" %2u", (udev->toggle[0] & (1 << i)) ? 1 : 0);
pr_debug("\n");
dev_dbg(dev, " toggle1(OUT):");
for (i = 0; i < 16; i++)
pr_debug(" %2u", (udev->toggle[1] & (1 << i)) ? 1 : 0);
pr_debug("\n");
dev_dbg(dev, " epmaxp_in :");
for (i = 0; i < 16; i++) {
if (udev->ep_in[i])
pr_debug(" %2u",
le16_to_cpu(udev->ep_in[i]->desc.wMaxPacketSize));
}
pr_debug("\n");
dev_dbg(dev, " epmaxp_out :");
for (i = 0; i < 16; i++) {
if (udev->ep_out[i])
pr_debug(" %2u",
le16_to_cpu(udev->ep_out[i]->desc.wMaxPacketSize));
}
pr_debug("\n");
dev_dbg(dev, "parent %s, bus %s\n", dev_name(&udev->parent->dev),
udev->bus->bus_name);
dev_dbg(dev, "have_langid %d, string_langid %d\n",
udev->have_langid, udev->string_langid);
dev_dbg(dev, "maxchild %d\n", udev->maxchild);
}
static void usbip_dump_request_type(__u8 rt)
{
switch (rt & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
pr_debug("DEVICE");
break;
case USB_RECIP_INTERFACE:
pr_debug("INTERF");
break;
case USB_RECIP_ENDPOINT:
pr_debug("ENDPOI");
break;
case USB_RECIP_OTHER:
pr_debug("OTHER ");
break;
default:
pr_debug("------");
break;
}
}
static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
{
if (!cmd) {
pr_debug(" : null pointer\n"<