linux/drivers/usb/gadget/legacy/dbgp.c

// SPDX-License-Identifier: GPL-2.0
/*
 * dbgp.c -- EHCI Debug Port device gadget
 *
 * Copyright (C) 2010 Stephane Duverger
 *
 * Released under the GPLv2.
 */

/* verbose messages */
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>

#include "u_serial.h"

#define DRIVER_VENDOR_ID
#define DRIVER_PRODUCT_ID

#define USB_DEBUG_MAX_PACKET_SIZE
#define DBGP_REQ_EP0_LEN
#define DBGP_REQ_LEN

static struct dbgp {} dbgp;

static struct usb_device_descriptor device_desc =;

static struct usb_debug_descriptor dbg_desc =;

static struct usb_endpoint_descriptor i_desc =;

static struct usb_endpoint_descriptor o_desc =;

#ifdef CONFIG_USB_G_DBGP_PRINTK
static int dbgp_consume(char *buf, unsigned len)
{
	char c;

	if (!len)
		return 0;

	c = buf[len-1];
	if (c != 0)
		buf[len-1] = 0;

	printk(KERN_NOTICE "%s%c", buf, c);
	return 0;
}

static void __disable_ep(struct usb_ep *ep)
{
	usb_ep_disable(ep);
}

static void dbgp_disable_ep(void)
{
	__disable_ep(dbgp.i_ep);
	__disable_ep(dbgp.o_ep);
}

static void dbgp_complete(struct usb_ep *ep, struct usb_request *req)
{
	int stp;
	int err = 0;
	int status = req->status;

	if (ep == dbgp.i_ep) {
		stp = 1;
		goto fail;
	}

	if (status != 0) {
		stp = 2;
		goto release_req;
	}

	dbgp_consume(req->buf, req->actual);

	req->length = DBGP_REQ_LEN;
	err = usb_ep_queue(ep, req, GFP_ATOMIC);
	if (err < 0) {
		stp = 3;
		goto release_req;
	}

	return;

release_req:
	kfree(req->buf);
	usb_ep_free_request(dbgp.o_ep, req);
	dbgp_disable_ep();
fail:
	dev_dbg(&dbgp.gadget->dev,
		"complete: failure (%d:%d) ==> %d\n", stp, err, status);
}

static int dbgp_enable_ep_req(struct usb_ep *ep)
{
	int err, stp;
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, GFP_KERNEL);
	if (!req) {
		err = -ENOMEM;
		stp = 1;
		goto fail_1;
	}

	req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL);
	if (!req->buf) {
		err = -ENOMEM;
		stp = 2;
		goto fail_2;
	}

	req->complete = dbgp_complete;
	req->length = DBGP_REQ_LEN;
	err = usb_ep_queue(ep, req, GFP_ATOMIC);
	if (err < 0) {
		stp = 3;
		goto fail_3;
	}

	return 0;

fail_3:
	kfree(req->buf);
fail_2:
	usb_ep_free_request(dbgp.o_ep, req);
fail_1:
	dev_dbg(&dbgp.gadget->dev,
		"enable ep req: failure (%d:%d)\n", stp, err);
	return err;
}

static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
{
	int err;
	ep->desc = desc;
	err = usb_ep_enable(ep);
	return err;
}

static int dbgp_enable_ep(void)
{
	int err, stp;

	err = __enable_ep(dbgp.i_ep, &i_desc);
	if (err < 0) {
		stp = 1;
		goto fail_1;
	}

	err = __enable_ep(dbgp.o_ep, &o_desc);
	if (err < 0) {
		stp = 2;
		goto fail_2;
	}

	err = dbgp_enable_ep_req(dbgp.o_ep);
	if (err < 0) {
		stp = 3;
		goto fail_3;
	}

	return 0;

fail_3:
	__disable_ep(dbgp.o_ep);
fail_2:
	__disable_ep(dbgp.i_ep);
fail_1:
	dev_dbg(&dbgp.gadget->dev, "enable ep: failure (%d:%d)\n", stp, err);
	return err;
}
#endif

static void dbgp_disconnect(struct usb_gadget *gadget)
{}

static void dbgp_unbind(struct usb_gadget *gadget)
{}

#ifdef CONFIG_USB_G_DBGP_SERIAL
static unsigned char tty_line;
#endif

static int dbgp_configure_endpoints(struct usb_gadget *gadget)
{}

static int dbgp_bind(struct usb_gadget *gadget,
		struct usb_gadget_driver *driver)
{}

static void dbgp_setup_complete(struct usb_ep *ep,
				struct usb_request *req)
{}

static int dbgp_setup(struct usb_gadget *gadget,
		      const struct usb_ctrlrequest *ctrl)
{}

static struct usb_gadget_driver dbgp_driver =;

static int __init dbgp_init(void)
{}

static void __exit dbgp_exit(void)
{}

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
module_init();
module_exit(dbgp_exit);