Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit b56ba47d authored by derfelot's avatar derfelot
Browse files

usb: gadget: Add Sony modifications to USB gadgets

Taken from Sony 47.2.A.10.107 stock kernel
parent 5e5bcb1d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -599,6 +599,13 @@ config USB_CONFIGFS_F_CCID
	  USB CCID function driver creats transport layer between the
	  userspace CCID component and the Windows Host.

config USB_ANDROID_PRODUCTION
	boolean "Production capable Android gadget"
	depends on USB_CONFIGFS
	default n
	help
	  Provides an Android gadget where iSerialNumber is set to 0.

source "drivers/usb/gadget/legacy/Kconfig"

endchoice
+9 −5
Original line number Diff line number Diff line
@@ -8,6 +8,11 @@
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

/* #define VERBOSE_DEBUG */

@@ -35,8 +40,7 @@
	(speed == USB_SPEED_SUPER ?\
	SSUSB_GADGET_VBUS_DRAW : CONFIG_USB_GADGET_VBUS_DRAW)

/* disable LPM by default */
static bool disable_l1_for_hs = true;
static bool disable_l1_for_hs;
module_param(disable_l1_for_hs, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(disable_l1_for_hs,
	"Disable support for L1 LPM for HS devices");
@@ -1701,9 +1705,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
				value = min(w_length, (u16) value);
			break;
		case USB_DT_BOS:
			if ((gadget_is_superspeed(gadget) &&
				(gadget->speed >= USB_SPEED_SUPER))
				 || !disable_l1_for_hs) {
			if (gadget_is_superspeed(gadget) &&
				((gadget->speed >= USB_SPEED_SUPER)
				 || !disable_l1_for_hs)) {
				value = bos_desc(cdev);
				value = min(w_length, (u16) value);
			}
+34 −0
Original line number Diff line number Diff line
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */
#include <linux/configfs.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -98,6 +103,7 @@ struct gadget_info {
	struct work_struct work;
	struct device *dev;
#endif
	bool isMSOSDesc;
};

static inline struct gadget_info *to_gadget_info(struct config_item *item)
@@ -148,6 +154,10 @@ struct gadget_config_name {
#define MAX_USB_STRING_LEN	126
#define MAX_USB_STRING_WITH_NULL_LEN	(MAX_USB_STRING_LEN+1)

/* vendor code */
#define MSOS_VENDOR_CODE	0x08
#define MSOS_GOOGLE_VENDOR_CODE	0x01

static int usb_string_copy(const char *s, char **s_copy)
{
	int ret;
@@ -334,6 +344,14 @@ err:
	return ret;
}

static ssize_t gadget_dev_desc_isMSOSDesc_show(struct config_item *item,
		char *page)
{
	struct gadget_info *gi = to_gadget_info(item);

	return snprintf(page, 3, "%s\n", gi->isMSOSDesc ? "Y" : "N");
}

CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
@@ -343,6 +361,7 @@ CONFIGFS_ATTR(gadget_dev_desc_, idProduct);
CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
CONFIGFS_ATTR(gadget_dev_desc_, UDC);
CONFIGFS_ATTR_RO(gadget_dev_desc_, isMSOSDesc);

static struct configfs_attribute *gadget_root_attrs[] = {
	&gadget_dev_desc_attr_bDeviceClass,
@@ -354,6 +373,7 @@ static struct configfs_attribute *gadget_root_attrs[] = {
	&gadget_dev_desc_attr_bcdDevice,
	&gadget_dev_desc_attr_bcdUSB,
	&gadget_dev_desc_attr_UDC,
	&gadget_dev_desc_attr_isMSOSDesc,
	NULL,
};

@@ -1344,7 +1364,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget,

		gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
		gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
#ifdef CONFIG_USB_ANDROID_PRODUCTION
		/* Set id to 0 to comply with Sony production tools */
		gi->cdev.desc.iSerialNumber = 0;
#else
		gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
#endif
	}

	if (gi->use_os_desc) {
@@ -1624,6 +1649,14 @@ static int android_setup(struct usb_gadget *gadget,
	if (value < 0)
		value = composite_setup(gadget, c);

	if ((c->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
		if (((c->bRequest == MSOS_GOOGLE_VENDOR_CODE) ||
			(c->bRequest == MSOS_VENDOR_CODE)) &&
			(c->bRequestType & USB_DIR_IN) && le16_to_cpu(c->wIndex == 4)) {
			gi->isMSOSDesc = true;
		}
	}

	spin_lock_irqsave(&cdev->lock, flags);
	if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
						cdev->config) {
@@ -1670,6 +1703,7 @@ static void android_disconnect(struct usb_gadget *gadget)
	if (!gi->unbinding)
		schedule_work(&gi->work);
	composite_disconnect(gadget);
	gi->isMSOSDesc = false;
}
#endif

+13 −2
Original line number Diff line number Diff line
@@ -13,6 +13,11 @@
 * GNU General Public License for more details.
 *
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include <linux/device.h>
#include <linux/usb/audio.h>
@@ -246,6 +251,7 @@ struct audio_source_config {

struct audio_dev {
	struct usb_function		func;
	u8				ctrl_id;
	struct snd_card			*card;
	struct snd_pcm			*pcm;
	struct snd_pcm_substream *substream;
@@ -616,9 +622,12 @@ static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 * Because the data interface supports multiple altsettings,
 * this audio_source function *MUST* implement a get_alt() method.
 */
static int audio_get_alt(struct usb_function *f, unsigned int intf)
static int audio_get_alt(struct usb_function *f, unsigned intf)
{
	struct audio_dev *audio = func_to_audio(f);
	if (intf == audio->ctrl_id) {
		return 0;
	}

	return audio->in_ep->enabled ? 1 : 0;
}
@@ -689,6 +698,8 @@ audio_bind(struct usb_configuration *c, struct usb_function *f)
	status = usb_interface_id(c, f);
	if (status < 0)
		goto fail;
	audio->ctrl_id = status;

	ac_interface_desc.bInterfaceNumber = status;

	/* AUDIO_AC_INTERFACE */
+77 −0
Original line number Diff line number Diff line
@@ -9,6 +9,11 @@
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include "f_gsi.h"
#include "rndis.h"
@@ -2557,6 +2562,30 @@ static int gsi_bind(struct usb_configuration *c, struct usb_function *f)

	switch (gsi->prot_id) {
	case IPA_USB_RNDIS:
		/* "Wireless" RNDIS6; auto-detected by Windows */
		pr_debug("%s: linux_support=%d\n",  __func__,
							gsi->linux_support);
		if (gsi->linux_support) {
			pr_info("%s: RNDIS5\n",  __func__);
			rndis_gsi_control_intf.bInterfaceClass =
						USB_CLASS_WIRELESS_CONTROLLER;
			rndis_gsi_control_intf.bInterfaceSubClass = 0x01;
			rndis_gsi_control_intf.bInterfaceProtocol = 0x03;
			rndis_gsi_iad_descriptor.bFunctionClass =
						USB_CLASS_WIRELESS_CONTROLLER;
			rndis_gsi_iad_descriptor.bFunctionSubClass = 0x01;
			rndis_gsi_iad_descriptor.bFunctionProtocol = 0x03;
		} else {
			pr_info("%s: RNDIS6\n",  __func__);
			rndis_gsi_control_intf.bInterfaceClass = USB_CLASS_MISC;
			rndis_gsi_control_intf.bInterfaceSubClass = 0x04;
			rndis_gsi_control_intf.bInterfaceProtocol = 0x01;
			rndis_gsi_iad_descriptor.bFunctionClass =
								USB_CLASS_MISC;
			rndis_gsi_iad_descriptor.bFunctionSubClass = 0x04;
			rndis_gsi_iad_descriptor.bFunctionProtocol = 0x01;
		}

		info.string_defs = rndis_gsi_string_defs;
		info.ctrl_desc = &rndis_gsi_control_intf;
		info.ctrl_str_idx = 0;
@@ -2941,6 +2970,8 @@ static struct f_gsi *gsi_function_init(enum ipa_usb_teth_prot prot_id)

	gsi->d_port.ipa_usb_wq = ipa_usb_wq;

	gsi->linux_support = false;

	ret = gsi_function_ctrl_port_init(gsi);
	if (ret) {
		kfree(gsi);
@@ -3107,6 +3138,51 @@ static ssize_t gsi_info_show(struct config_item *item, char *page)
	return ret;
}

static ssize_t gsi_linux_support_show(struct config_item *item, char *page)
{
	struct f_gsi *gsi = to_gsi_opts(item)->gsi;
	int ret;

	switch (gsi->prot_id) {
	case IPA_USB_RNDIS:
		/* "Y\n\0" 3characters */
		ret = snprintf(page, 3, "%c\n", gsi->linux_support ? 'Y' : 'N');
		break;
	default:
		ret = EBADR;
		break;
	}

	return ret;
}

static ssize_t gsi_linux_support_store(struct config_item *item,
						 const char *page, size_t len)
{
	struct f_gsi *gsi = to_gsi_opts(item)->gsi;
	bool val;
	int ret = 0;

	switch (gsi->prot_id) {
	case IPA_USB_RNDIS:
		ret = strtobool(page, &val);
		if (ret)
			break;
		gsi->linux_support = val;
		pr_info("%s: set linux_support=%d.\n",  __func__,
							gsi->linux_support);
		break;
	default:
		ret = -EBADR;
		break;
	}

	if (ret)
		len = ret;
	return len;
}

CONFIGFS_ATTR(gsi_, linux_support);
CONFIGFS_ATTR_RO(gsi_, info);

static ssize_t gsi_rndis_wceis_show(struct config_item *item, char *page)
@@ -3134,6 +3210,7 @@ CONFIGFS_ATTR(gsi_, rndis_wceis);

static struct configfs_attribute *gsi_rndis_attrs[] = {
	&gsi_attr_info,
	&gsi_attr_linux_support,
	&gsi_attr_rndis_wceis,
	NULL,
};
Loading