linux/drivers/usb/usbip/vhci_hcd.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2003-2008 Takahiro Hirofuchi
 * Copyright (C) 2015-2016 Nobuo Iwata
 */

#include <linux/init.h>
#include <linux/file.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include "usbip_common.h"
#include "vhci.h"

#define DRIVER_AUTHOR
#define DRIVER_DESC

/*
 * TODO
 *	- update root hub emulation
 *	- move the emulation code to userland ?
 *		porting to other operating systems
 *		minimize kernel code
 *	- add suspend/resume code
 *	- clean up everything
 */

/* See usb gadget dummy hcd */

static int vhci_hub_status(struct usb_hcd *hcd, char *buff);
static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			    u16 wIndex, char *buff, u16 wLength);
static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
			    gfp_t mem_flags);
static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
static int vhci_start(struct usb_hcd *vhci_hcd);
static void vhci_stop(struct usb_hcd *hcd);
static int vhci_get_frame_number(struct usb_hcd *hcd);

static const char driver_name[] =;
static const char driver_desc[] =;

int vhci_num_controllers =;
struct vhci *vhcis;

static const char * const bit_desc[] =;

static const char * const bit_desc_ss[] =;

static void dump_port_status_diff(u32 prev_status, u32 new_status, bool usb3)
{}

void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
{}

static void rh_port_disconnect(struct vhci_device *vdev)
{}

#define PORT_C_MASK

/*
 * Returns 0 if the status hasn't changed, or the number of bytes in buf.
 * Ports are 0-indexed from the HCD point of view,
 * and 1-indexed from the USB core pointer of view.
 *
 * @buf: a bitmap to show which port status has been changed.
 *  bit  0: reserved
 *  bit  1: the status of port 0 has been changed.
 *  bit  2: the status of port 1 has been changed.
 *  ...
 */
static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
{}

/* usb 3.0 root hub device descriptor */
static struct {} __packed usb3_bos_desc =;

static inline void
ss_hub_descriptor(struct usb_hub_descriptor *desc)
{}

static inline void hub_descriptor(struct usb_hub_descriptor *desc)
{}

static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			    u16 wIndex, char *buf, u16 wLength)
{}

static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
{}

static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
{}

/*
 * vhci_rx gives back the urb after receiving the reply of the urb.  If an
 * unlink pdu is sent or not, vhci_rx receives a normal return pdu and gives
 * back its urb. For the driver unlinking the urb, the content of the urb is
 * not important, but the calling to its completion handler is important; the
 * completion of unlinking is notified by the completion handler.
 *
 *
 * CLIENT SIDE
 *
 * - When vhci_hcd receives RET_SUBMIT,
 *
 *	- case 1a). the urb of the pdu is not unlinking.
 *		- normal case
 *		=> just give back the urb
 *
 *	- case 1b). the urb of the pdu is unlinking.
 *		- usbip.ko will return a reply of the unlinking request.
 *		=> give back the urb now and go to case 2b).
 *
 * - When vhci_hcd receives RET_UNLINK,
 *
 *	- case 2a). a submit request is still pending in vhci_hcd.
 *		- urb was really pending in usbip.ko and urb_unlink_urb() was
 *		  completed there.
 *		=> free a pending submit request
 *		=> notify unlink completeness by giving back the urb
 *
 *	- case 2b). a submit request is *not* pending in vhci_hcd.
 *		- urb was already given back to the core driver.
 *		=> do not give back the urb
 *
 *
 * SERVER SIDE
 *
 * - When usbip receives CMD_UNLINK,
 *
 *	- case 3a). the urb of the unlink request is now in submission.
 *		=> do usb_unlink_urb().
 *		=> after the unlink is completed, send RET_UNLINK.
 *
 *	- case 3b). the urb of the unlink request is not in submission.
 *		- may be already completed or never be received
 *		=> send RET_UNLINK
 *
 */
static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{}

static void vhci_cleanup_unlink_list(struct vhci_device *vdev,
		struct list_head *unlink_list)
{}

static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
{}

/*
 * The important thing is that only one context begins cleanup.
 * This is why error handling and cleanup become simple.
 * We do not want to consider race condition as possible.
 */
static void vhci_shutdown_connection(struct usbip_device *ud)
{}

static void vhci_device_reset(struct usbip_device *ud)
{}

static void vhci_device_unusable(struct usbip_device *ud)
{}

static void vhci_device_init(struct vhci_device *vdev)
{}

static int hcd_name_to_id(const char *name)
{}

static int vhci_setup(struct usb_hcd *hcd)
{}

static int vhci_start(struct usb_hcd *hcd)
{}

static void vhci_stop(struct usb_hcd *hcd)
{}

static int vhci_get_frame_number(struct usb_hcd *hcd)
{}

#ifdef CONFIG_PM

/* FIXME: suspend/resume */
static int vhci_bus_suspend(struct usb_hcd *hcd)
{}

static int vhci_bus_resume(struct usb_hcd *hcd)
{}

#else

#define vhci_bus_suspend
#define vhci_bus_resume
#endif

/* Change a group of bulk endpoints to support multiple stream IDs */
static int vhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
	struct usb_host_endpoint **eps, unsigned int num_eps,
	unsigned int num_streams, gfp_t mem_flags)
{}

/* Reverts a group of bulk endpoints back to not using stream IDs. */
static int vhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
	struct usb_host_endpoint **eps, unsigned int num_eps,
	gfp_t mem_flags)
{}

static const struct hc_driver vhci_hc_driver =;

static int vhci_hcd_probe(struct platform_device *pdev)
{}

static void vhci_hcd_remove(struct platform_device *pdev)
{}

#ifdef CONFIG_PM

/* what should happen for USB/IP under suspend/resume? */
static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
{}

static int vhci_hcd_resume(struct platform_device *pdev)
{}

#else

#define vhci_hcd_suspend
#define vhci_hcd_resume

#endif

static struct platform_driver vhci_driver =;

static void del_platform_devices(void)
{}

static int __init vhci_hcd_init(void)
{}

static void __exit vhci_hcd_exit(void)
{}

module_init();
module_exit(vhci_hcd_exit);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();