Update Android USB Gadgets to latest from the Legend tree

file:bfd174f753a64854e9471eb0a470c664047c23ea -> file:2bd26451bd63b69cb0e3c06b9d5481880127f79c
--- a/arch/arm/mach-msm/include/mach/msm_hsusb.h
+++ b/arch/arm/mach-msm/include/mach/msm_hsusb.h
@@ -47,6 +47,10 @@ struct msm_hsusb_platform_data {
/* 1 : uart, 0 : usb */
void (*usb_uart_switch)(int);
void (*config_usb_id_gpios)(bool enable);
+ void (*usb_hub_enable)(bool);
+ void (*serial_debug_gpios)(int);
+ int (*china_ac_detect)(void);
+ void (*disable_usb_charger)(void);
/* val, reg pairs terminated by -1 */
int *phy_init_seq;
@@ -76,8 +80,11 @@ struct msm_hsusb_platform_data {
#endif
char *serial_number;
int usb_id_pin_gpio;
+ int dock_pin_gpio;
+ int id_pin_irq;
bool enable_car_kit_detect;
__u8 accessory_detect;
+ bool dock_detect;
};
int usb_get_connect_type(void);
file:2cb1e7ba34043154b2ab86cbdc50785eeb9cb82c -> file:a2726b0b6b900239b8ba7774db2812bb4c234f91
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -33,6 +33,8 @@
#include <linux/usb/gadget.h>
#include "gadget_chips.h"
+#include <linux/wakelock.h>
+#include <mach/perflock.h>
/*
* Kbuild is not very cooperative with respect to linking separately
@@ -52,6 +54,8 @@ MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");
static const char longname[] = "Gadget Android";
+static struct wake_lock usb_rndis_idle_wake_lock;
+static struct perf_lock usb_rndis_perf_lock;
enum {
USB_FUNCTION_UMS = 0,
@@ -63,8 +67,13 @@ enum {
USB_FUNCTION_FSYNC,
USB_FUNCTION_MTP,
USB_FUNCTION_MODEM,
+ USB_FUNCTION_ECM,
+ USB_FUNCTION_ACM,
};
+#define PID_RNDIS 0x0ffe
+#define PID_ECM 0x0ff8
+#define PID_ACM 0x0ff4
#ifdef CONFIG_USB_ANDROID_MTP
#define MS_VENDOR_CODE 0x0b
#define FEATURE_DESC_SIZE 64
@@ -104,6 +113,7 @@ static struct ms_comp_feature_descriptor
.bFirstInterfaceNumber2 = 1,
.resv4 = 1,
};
+
#endif
/* Default vendor and product IDs, overridden by platform data */
@@ -431,7 +441,9 @@ int android_switch_function(unsigned fun
struct usb_function *f;
struct android_dev *dev = _android_dev;
int product_id;
+
printk(KERN_INFO "%s: %u\n", __func__, func);
+
list_for_each_entry(f, &android_config_driver.functions, list) {
if ((func & (1 << USB_FUNCTION_UMS)) &&
!strcmp(f->name, "usb_mass_storage"))
@@ -439,10 +451,22 @@ int android_switch_function(unsigned fun
else if ((func & (1 << USB_FUNCTION_ADB)) &&
!strcmp(f->name, "adb"))
f->hidden = 0;
+ else if ((func & (1 << USB_FUNCTION_ECM)) &&
+ !strcmp(f->name, "cdc_ethernet"))
+ f->hidden = 0;
+ else if ((func & (1 << USB_FUNCTION_ACM)) &&
+ !strcmp(f->name, "acm"))
+ f->hidden = 0;
else if ((func & (1 << USB_FUNCTION_RNDIS)) &&
- !strcmp(f->name, "ether"))
+ !strcmp(f->name, "ether")) {
+ if (f->hidden) {
+ printk("%s: rndis perf lock\n", __func__);
+ wake_lock(&usb_rndis_idle_wake_lock);
+ if (!is_perf_lock_active(&usb_rndis_perf_lock))
+ perf_lock(&usb_rndis_perf_lock);
+ }
f->hidden = 0;
- else if ((func & (1 << USB_FUNCTION_DIAG)) &&
+ } else if ((func & (1 << USB_FUNCTION_DIAG)) &&
!strcmp(f->name, "diag"))
f->hidden = 0;
else if ((func & (1 << USB_FUNCTION_MODEM)) &&
@@ -461,8 +485,15 @@ int android_switch_function(unsigned fun
else if ((func & (1 << USB_FUNCTION_PROJECTOR)) &&
!strcmp(f->name, "projector"))
f->hidden = 0;
- else
+ else {
+ if (!strcmp(f->name, "ether") && !f->hidden) {
+ printk("%s: rndis perf unlock\n", __func__);
+ wake_unlock(&usb_rndis_idle_wake_lock);
+ if (is_perf_lock_active(&usb_rndis_perf_lock))
+ perf_unlock(&usb_rndis_perf_lock);
+ }
f->hidden = 1;
+ }
}
product_id = get_product_id(dev);
device_desc.idProduct = __constant_cpu_to_le16(product_id);
@@ -472,7 +503,7 @@ int android_switch_function(unsigned fun
/* We need to specify the COMM class in the device descriptor
* if we are using RNDIS.
*/
- if (func & (1 << USB_FUNCTION_RNDIS))
+ if (product_id == PID_RNDIS || product_id == PID_ECM || product_id == PID_ACM)
dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
else
dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
@@ -491,7 +522,7 @@ int android_switch_function(unsigned fun
return 0;
}
-void android_enable_function(struct usb_function *f, int enable, bool reset)
+void android_enable_function(struct usb_function *f, int enable)
{
struct android_dev *dev = _android_dev;
int disable = !enable;
@@ -508,16 +539,17 @@ void android_enable_function(struct usb_
/* We need to specify the COMM class in the device descriptor
* if we are using RNDIS.
*/
- if (!strcmp(f->name, "ether")) {
- if (enable)
- dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
- else
- dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
- }
+ if (product_id == PID_RNDIS)
+ dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
+ else
+ dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
#endif
+ if (product_id == PID_ECM || product_id == PID_ACM)
+ dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
+ else
+ dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
#ifdef CONFIG_USB_GADGET_MSM_72K
- if (reset)
msm_hsusb_request_reset();
#else
/* force reenumeration */
@@ -596,6 +628,9 @@ static int __init init(void)
dev->product_id = PRODUCT_ID;
_android_dev = dev;
+ wake_lock_init(&usb_rndis_idle_wake_lock, WAKE_LOCK_IDLE, "rndis_idle_lock");
+ perf_lock_init(&usb_rndis_perf_lock, PERF_LOCK_HIGHEST, "rndis");
+
return platform_driver_register(&android_platform_driver);
}
module_init(init);
file:946cbcfbcfbf6173a124e4c1676c6b245edf55ad -> file:4e970cf0e29ae364b34c5e7436906e95db313952
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -2013,9 +2013,6 @@ static int __init usba_udc_probe(struct
} else {
disable_irq(gpio_to_irq(udc->vbus_pin));
}
- } else {
- /* gpio_request fail so use -EINVAL for gpio_is_valid */
- udc->vbus_pin = -EINVAL;
}
}
file:a15a5e943366e8de554bfbc9155334198159545c -> file:edd6310b9bae3536580f00e5bb967bdedacc66e4
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -26,6 +26,7 @@
#include <linux/device.h>
#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
/*
@@ -88,7 +89,7 @@ static ssize_t enable_store(
sscanf(buf, "%d", &value);
if (driver->enable_function)
- driver->enable_function(f, value, true);
+ driver->enable_function(f, value);
else
f->hidden = !value;
@@ -276,6 +277,7 @@ static struct usb_function *get_function
struct usb_configuration *config = cdev->config;
enum usb_device_speed speed = cdev->gadget->speed;
struct usb_function *f;
+ struct usb_descriptor_header **descriptors;
struct usb_descriptor_header *descriptor;
struct usb_interface_descriptor *intf_desc;
int i;
@@ -285,7 +287,7 @@ static struct usb_function *get_function
return NULL;
if (f->hidden)
continue;
-
+#if 0
if (speed == USB_SPEED_HIGH)
descriptor = *(f->hs_descriptors);
else
@@ -294,6 +296,19 @@ static struct usb_function *get_function
if (intf_desc->bDescriptorType == USB_DT_INTERFACE &&
intf_desc->bInterfaceNumber == intf)
return f;
+#endif
+ if (speed == USB_SPEED_HIGH)
+ descriptors = f->hs_descriptors;
+ else
+ descriptors = f->descriptors;
+
+ while ((descriptor = *descriptors++) != NULL) {
+ intf_desc = (struct usb_interface_descriptor *)descriptor;
+ if (intf_desc->bDescriptorType == USB_DT_INTERFACE &&
+ intf_desc->bInterfaceNumber == intf) {
+ return f;
+ }
+ }
}
return NULL;
}
@@ -309,6 +324,9 @@ static int config_buf(struct usb_configu
int status;
int interfaceCount = 0;
u8 *dest;
+#if (defined(CONFIG_USB_ANDROID_ECM) || defined(CONFIG_USB_ANDROID_ACM))
+ int is_cdc = 0;
+#endif
/* write the config descriptor */
c = buf;
@@ -351,10 +369,47 @@ static int config_buf(struct usb_configu
while ((descriptor = *descriptors++) != NULL) {
intf = (struct usb_interface_descriptor *)dest;
if (intf->bDescriptorType == USB_DT_INTERFACE) {
- intf->bInterfaceNumber = interfaceCount;
- intf = (struct usb_interface_descriptor *)descriptor;
- intf->bInterfaceNumber = interfaceCount++;
+#if (defined(CONFIG_USB_ANDROID_ECM) || defined(CONFIG_USB_ANDROID_ACM))
+ /* CDC ACM/ECM */
+ if (intf->bInterfaceClass == USB_CLASS_COMM &&
+ (intf->bInterfaceSubClass == USB_CDC_SUBCLASS_ETHERNET ||
+ intf->bInterfaceSubClass == USB_CDC_SUBCLASS_ACM))
+ is_cdc = 1;
+ else
+ is_cdc = 0;
+#endif
+ /* don't increment bInterfaceNumber for alternate settings */
+ if (intf->bAlternateSetting == 0) {
+ intf->bInterfaceNumber = interfaceCount;
+ intf = (struct usb_interface_descriptor *)descriptor;
+ intf->bInterfaceNumber = interfaceCount++;
+ } else {
+ intf->bInterfaceNumber = interfaceCount - 1;
+ intf = (struct usb_interface_descriptor *)descriptor;
+ intf->bInterfaceNumber = interfaceCount - 1;
+ }
+
+ }
+#if (defined(CONFIG_USB_ANDROID_ECM) || defined(CONFIG_USB_ANDROID_ACM))
+ /* set interface number dynamically for CDC interface descriptor */
+ else if (is_cdc && intf->bDescriptorType == USB_DT_CS_INTERFACE) {
+ __u8 subtype = *(dest+2);
+ if (subtype == USB_CDC_UNION_TYPE) {
+ struct usb_cdc_union_desc *desc;
+ desc = (struct usb_cdc_union_desc *)dest;
+ desc->bMasterInterface0 = interfaceCount - 1;
+ desc->bSlaveInterface0 = interfaceCount;
+ } else if (subtype == USB_CDC_CALL_MANAGEMENT_TYPE) {
+ struct usb_cdc_call_mgmt_descriptor *desc;
+ desc = (struct usb_cdc_call_mgmt_descriptor *)dest;
+ desc->bDataInterface = interfaceCount;
+ }
+ } else if (intf->bDescriptorType == USB_DT_INTERFACE_ASSOCIATION) {
+ struct usb_interface_assoc_descriptor *desc;
+ desc = (struct usb_interface_assoc_descriptor *)dest;
+ desc->bFirstInterface = interfaceCount;
}
+#endif
dest += intf->bLength;
}
@@ -472,6 +527,7 @@ static int set_config(struct usb_composi
int result = -EINVAL;
unsigned power = gadget_is_otg(gadget) ? 8 : 100;
int tmp;
+ int interfaceCount = 0;
if (cdev->config)
reset_config(cdev);
@@ -508,15 +564,18 @@ static int set_config(struct usb_composi
if (!f)
break;
+ if (f->hidden)
+ continue;
- result = f->set_alt(f, tmp, 0);
+ result = f->set_alt(f, interfaceCount, 0);
if (result < 0) {
DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
- tmp, f->name, f, result);
+ interfaceCount, f->name, f, result);
reset_config(cdev);
goto done;
}
+ interfaceCount++;
}
/* when we return, be sure our power usage is valid */
@@ -714,6 +773,8 @@ static int get_string(struct usb_composi
return len;
}
list_for_each_entry(f, &c->functions, list) {
+ if (f->hidden)
+ continue;
if (!f->strings)
continue;
len = lookup_string(f->strings, buf, language, id);
file:28723f60f628c27d591907fa005f12fe2ee766f3 -> file:78253430b80e5c3b4daaaa15907ff7d4e7930d9d
--- a/drivers/usb/gadget/diag.c
+++ b/drivers/usb/gadget/diag.c
@@ -29,6 +29,8 @@
#include <linux/usb/android_composite.h>
+/*#define DIAG_DEBUG*/
+
#define NO_HDLC 1
#define ROUTE_TO_USERSPACE 1
@@ -72,6 +74,9 @@ static void TRACE(const char *tag, const
}
#endif
+
+
+
#define HDLC_MAX 4096
#define SMD_MAX 8192
@@ -79,8 +84,8 @@ static void TRACE(const char *tag, const
#define RX_REQ_BUF_SZ 8192
/* number of tx/rx requests to allocate */
-#define TX_REQ_NUM 4
-#define RX_REQ_NUM 4
+#define TX_REQ_NUM 32
+#define RX_REQ_NUM 32
struct diag_context {
struct usb_function function;
@@ -219,6 +224,7 @@ static inline struct diag_context *func_
return container_of(f, struct diag_context, function);
}
+static int msm_diag_probe(struct platform_device *pdev);
static void smd_try_to_send(struct diag_context *ctxt);
static void smd_diag_notify(void *priv, unsigned event);
@@ -334,6 +340,10 @@ static long diag_ioctl(struct file *file
unsigned char temp_id_table[ID_TABLE_SZ];
printk(KERN_INFO "diag:diag_ioctl() cmd=%d\n", cmd);
+#ifdef DIAG_DEBUG
+ printk(KERN_INFO "%s:%s(parent:%s): tgid=%d\n", __func__,
+ current->comm, current->parent->comm, current->tgid);
+#endif
if (_IOC_TYPE(cmd) != USB_DIAG_IOC_MAGIC)
return -ENOTTY;
@@ -343,7 +353,7 @@ static long diag_ioctl(struct file *file
if (copy_from_user(&tmp_value, argp, sizeof(int)))
return -EFAULT;
printk(KERN_INFO "diag: enable %d\n", tmp_value);
- android_enable_function(&_context.function, tmp_value, true);
+ android_enable_function(&_context.function, tmp_value);
smd_diag_enable("diag_ioctl", tmp_value);
/* force diag_read to return error when disable diag */
if (tmp_value == 0)
@@ -456,6 +466,7 @@ static ssize_t diag_write(struct file *f
((req = req_get(ctxt, &ctxt->tx_req_idle)) || !ctxt->online));
mutex_lock(&ctxt->user_lock);
+
if (ret < 0) {
pr_err("%s: wait_event_interruptible error %d\n",
__func__, ret);
@@ -503,11 +514,14 @@ static int diag_open(struct inode *ip, s
int rc = 0;
mutex_lock(&ctxt->user_lock);
+
if (ctxt->opened) {
pr_err("%s: already opened\n", __func__);
rc = -EBUSY;
goto done;
}
+
+
ctxt->user_read_len = 0;
ctxt->user_readp = 0;
if (!ctxt->user_read_buf) {
@@ -605,6 +619,7 @@ static int diag2arm9_release(struct inod
printk(KERN_INFO "%s\n", __func__);
mutex_lock(&ctxt->diag2arm9_lock);
ctxt->diag2arm9_opened = false;
+ ctxt->is2ARM11 = 0;
wake_up(&ctxt->read_arm9_wq);
mutex_lock(&ctxt->diag2arm9_read_lock);
while ((req = req_get(ctxt, &ctxt->rx_arm9_idle)))
@@ -909,6 +924,7 @@ again:
ctxt->rx_count += r;
if (!ctxt->online) {
+ /* printk("$$$ discard %d\n", r);*/
req_put(ctxt, &ctxt->tx_req_idle, req);
goto again;
}
@@ -1161,7 +1177,6 @@ static void diag_function_disable(struct
usb_ep_disable(ctxt->in);
usb_ep_disable(ctxt->out);
}
-
#if defined(CONFIG_MSM_N_WAY_SMD)
static void diag_qdsp_send(struct diag_context *ctxt)
{
@@ -1208,31 +1223,33 @@ static void diag_qdsp_notify(void *priv,
diag_qdsp_send(ctxt);
}
+static struct platform_driver msm_smd_qdsp_ch1_driver = {
+ .probe = msm_diag_probe,
+ .driver = {
+ .name = "DSP_DIAG",
+ .owner = THIS_MODULE,
+ },
+};
+#endif
+
static int msm_diag_probe(struct platform_device *pdev)
{
struct diag_context *ctxt = &_context;
ctxt->pdev = pdev;
printk(KERN_INFO "diag:msm_diag_probe(), pdev->id=0x%x\n", pdev->id);
+#if defined(CONFIG_MSM_N_WAY_SMD)
if (pdev->id == 1)
smd_open("DSP_DIAG", &ctxt->chqdsp, ctxt, diag_qdsp_notify);
+#endif
return 0;
}
-static struct platform_driver msm_smd_qdsp_ch1_driver = {
- .probe = msm_diag_probe,
- .driver = {
- .name = "DSP_DIAG",
- .owner = THIS_MODULE,
- },
-};
-#endif
-
static int diag_set_enabled(const char *val, struct kernel_param *kp)
{
int enabled = simple_strtol(val, NULL, 0);
if (_context.cdev)
- android_enable_function(&_context.function, enabled, true);
+ android_enable_function(&_context.function, enabled);
_context.function_enable = !!enabled;
smd_diag_enable("diag_set_enabled", enabled);
return 0;
@@ -1278,7 +1295,12 @@ int diag_bind_config(struct usb_configur
ctxt->function.set_alt = diag_function_set_alt;
ctxt->function.disable = diag_function_disable;
+/* Workaround: enable diag first */
+#ifdef CONFIG_MACH_MECHA
+ ctxt->function.hidden = 0;
+#else
ctxt->function.hidden = !_context.function_enable;
+#endif
if (!ctxt->function.hidden)
smd_diag_enable("diag_bind_config", 1);
file:5df34c01ab71071396a02bf5709ac9d1dc8b21be -> file:25c80f7024f0de10f68dc2e582029b62f142187f
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -32,6 +32,7 @@
#include <linux/usb/android_composite.h>
#include <mach/board.h>
+#include <linux/wakelock.h>
#define BULK_BUFFER_SIZE 4096
@@ -40,6 +41,7 @@
#define RX_REQ_MAX 32
static const char shortname[] = "android_adb";
+static struct wake_lock adb_idle_wake_lock;
struct adb_dev {
struct usb_function function;
@@ -449,6 +451,7 @@ static ssize_t adb_write(struct file *fp
r = -EIO;
break;
}
+ wake_lock_timeout(&adb_idle_wake_lock, HZ / 2);
buf += xfer;
count -= xfer;
@@ -510,7 +513,7 @@ static int adb_enable_open(struct inode
}
printk(KERN_INFO "enabling adb\n");
- android_enable_function(&_adb_dev->function, 1, true);
+ android_enable_function(&_adb_dev->function, 1);
return 0;
}
@@ -518,7 +521,7 @@ static int adb_enable_open(struct inode
static int adb_enable_release(struct inode *ip, struct file *fp)
{
printk(KERN_INFO "disabling adb\n");
- android_enable_function(&_adb_dev->function, 0, true);
+ android_enable_function(&_adb_dev->function, 0);
atomic_dec(&adb_enable_excl);
return 0;
}
@@ -697,6 +700,10 @@ static int adb_bind_config(struct usb_co
if (board_mfg_mode() != 2)
dev->function.hidden = 1;
+/* Workaround: enable adb first */
+#ifdef CONFIG_MACH_MECHA
+ dev->function.hidden = 0;
+#endif
/* _adb_dev must be set before calling usb_gadget_register_driver */
_adb_dev = dev;
@@ -732,6 +739,7 @@ static struct android_usb_function adb_f
static int __init init(void)
{
printk(KERN_INFO "f_adb init\n");
+ wake_lock_init(&adb_idle_wake_lock, WAKE_LOCK_IDLE, "adb_idle_lock");
android_register_function(&adb_function);
return 0;
}
file:cfaf0af25a5e0a27a37f396c62b3ee099d4f82d9 -> file:d205953b12fa9bd5dd19c61b8ce7cc112de5dbb2
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -74,6 +74,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/android_composite.h>
#include <mach/board.h>
+#include <mach/msm_hsusb.h>
#include "gadget_chips.h"
@@ -201,6 +202,7 @@ struct bulk_cs_wrap {
#define SC_WRITE_6 0x0a
#define SC_WRITE_10 0x2a
#define SC_WRITE_12 0xaa
+#define SC_PASCAL_MODE 0xff
/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
#define SS_NO_SENSE 0
@@ -357,7 +359,6 @@ struct fsg_dev {
u32 usb_amount_left;
unsigned int nluns;
- unsigned int board_nluns;
struct lun *luns;
struct lun *curlun;
@@ -415,7 +416,8 @@ static void fsg_set_ums_state(int connec
printk(KERN_INFO "%s: %d\n", __func__, connect_status);
/* USB connected */
if (connect_status == 1) {
- if (!the_fsg->ums_state) {
+ /* only need to change state when connect to USB host */
+ if (!the_fsg->ums_state && usb_get_connect_type() == 1) {
the_fsg->ums_state = 1;
printk(KERN_INFO "ums: set state 1\n");
switch_set_state(&the_fsg->sdev, 1);
@@ -1541,7 +1543,7 @@ static int do_start_stop(struct fsg_dev
if (backing_file_is_open(curlun)) {
close_backing_file(fsg, curlun);
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
- if (curlun->cdrom || board_mfg_mode() == 1) {
+ if (curlun->cdrom) {
printk(KERN_INFO "ums: eject\n");
kobject_uevent_env(&fsg->sdev.dev->kobj,
KOBJ_CHANGE, envp);
@@ -2164,6 +2166,15 @@ static int do_scsi_command(struct fsg_de
"RESERVE(6)")) == 0)
reply = do_reserve(fsg, bh);
break;
+#ifdef CONFIG_USB_ANDROID_ACM
+ case SC_PASCAL_MODE:
+ printk(KERN_INFO "SC_PASCAL_MODE\n");
+ if (!strncmp("RDEVCHG=PASCAL", (char *)&fsg->cmnd[1], 14)) {
+ printk(KERN_INFO "usb: switch to CDC ACM\n");
+ android_switch_function(0x400);
+ }
+ break;
+#endif
/* Some mandatory commands that we recognize but don't implement.
* They don't mean much in this setting. It's left as an exercise
* for anyone interested to implement RESERVE and RELEASE in terms
@@ -3081,38 +3092,10 @@ static void fsg_function_disable(struct
raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
}
-static ssize_t store_lun_num(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned nluns;
- struct fsg_dev *fsg = the_fsg;
- nluns = simple_strtoul(buf, NULL, 10);
- if (nluns > 0 && nluns <= fsg->board_nluns && (nluns != fsg->nluns)) {
- fsg->nluns = nluns;
- android_usb_set_connected(0);
- msleep(10);
- android_usb_set_connected(1);
- }
- return count;
-}
-
-static ssize_t show_lun_num(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- unsigned length;
- struct fsg_dev *fsg = the_fsg;
- length = sprintf(buf, "%d\n", fsg->nluns);
- return length;
-}
-
-static DEVICE_ATTR(lun_num, 0644, show_lun_num, store_lun_num);
-
-
static int __init fsg_probe(struct platform_device *pdev)
{
struct usb_mass_storage_platform_data *pdata = pdev->dev.platform_data;
struct fsg_dev *fsg = the_fsg;
- int rc;
fsg->pdev = pdev;
printk(KERN_INFO "fsg_probe pdata: %p\n", pdata);
@@ -3126,13 +3109,9 @@ static int __init fsg_probe(struct platf
if (pdata->release)
fsg->release = pdata->release;
- fsg->nluns = fsg->board_nluns = pdata->nluns;
+ fsg->nluns = pdata->nluns;
fsg->cdrom_lun = pdata->cdrom_lun;
}
- rc = device_create_file(&the_fsg->pdev->dev,
- &dev_attr_lun_num);
- if (rc != 0)
- printk(KERN_WARNING "dev_attr_lun_num failed\n");
return 0;
}
file:e2ae04222bb60f32e6eb373c2cc170cf8070caf2 -> file:c61180770b5e6d2cbcd1e9906f4ca6d32b0ec81d
--- a/drivers/usb/gadget/f_projector.c
+++ b/drivers/usb/gadget/f_projector.c
@@ -710,7 +710,7 @@ static ssize_t store_enable(struct devic
{
int _enabled = simple_strtol(buf, NULL, 0);
printk(KERN_INFO "projector: %d\n", _enabled);
- android_enable_function(&_projector_dev.function, _enabled, true);
+ android_enable_function(&_projector_dev.function, _enabled);
_projector_dev.enabled = _enabled;
return count;
}
file:3360b481b9dc8c6ed0eb6903a403fe99188deb3d -> file:b800432d718ef6269e5aeca0fd34f281b05037d5
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -118,8 +118,17 @@ static unsigned int bitrate(struct usb_g
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
#define STATUS_BYTECOUNT 8 /* 8 bytes data */
-
/* interface descriptor: */
+static struct usb_interface_assoc_descriptor rndis_iad = {
+ .bLength = sizeof rndis_iad,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 0,
+ .bInterfaceCount = 2,
+ .bFunctionClass = USB_CLASS_COMM,
+ .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
+ .bFunctionProtocol = 0,
+ .iFunction = 0,
+};
static struct usb_interface_descriptor rndis_control_intf __initdata = {
.bLength = sizeof rndis_control_intf,
@@ -210,6 +219,7 @@ static struct usb_endpoint_descriptor fs
};
static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+ (struct usb_descriptor_header *) &rndis_iad,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
(struct usb_descriptor_header *) &header_desc,
@@ -254,6 +264,7 @@ static struct usb_endpoint_descriptor hs
};
static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+ (struct usb_descriptor_header *) &rndis_iad,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
(struct usb_descriptor_header *) &header_desc,
@@ -273,6 +284,7 @@ static struct usb_descriptor_header *eth
static struct usb_string rndis_string_defs[] = {
[0].s = "RNDIS Communications Control",
[1].s = "RNDIS Ethernet Data",
+ [2].s = "RNDIS",
{ } /* end of list */
};
@@ -798,6 +810,13 @@ int __init rndis_bind_config(struct usb_
return status;
rndis_string_defs[1].id = status;
rndis_data_intf.iInterface = status;
+
+ /* function label */
+ status = usb_string_id(c->cdev);
+ if (status > 0) {
+ rndis_iad.iFunction = status;
+ rndis_string_defs[2].id = status;
+ }
}
/* allocate and initialize one new instance */
file:158f7870969523f30c6efa5ef60c6c430ae67dd2 -> file:795978d5afb3b6f738e53decac596ae54c746ff8
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -16,8 +16,12 @@
#include "u_serial.h"
#include "gadget_chips.h"
+#include <linux/wakelock.h>
#include <mach/perflock.h>
+static struct wake_lock vbus_idle_wake_lock;
+static struct perf_lock usb_perf_lock;
+
#define CONFIG_MODEM_SUPPORT
/*
* This function packages a simple "generic serial" port with no real
@@ -248,9 +252,6 @@ static struct usb_gadget_strings *serial
&serial_string_table,
NULL,
};
-
-static struct perf_lock usb_perf_lock;
-
#ifdef CONFIG_MODEM_SUPPORT
static void gser_complete_set_line_coding(struct usb_ep *ep,
struct usb_request *req)
@@ -795,14 +796,17 @@ static int modem_set_enabled(const char
if (!gser)
return 0;
if (enabled) {
+ wake_lock(&vbus_idle_wake_lock);
if (!is_perf_lock_active(&usb_perf_lock))
perf_lock(&usb_perf_lock);
- } else {
+ }
+ else {
+ wake_unlock(&vbus_idle_wake_lock);
if (is_perf_lock_active(&usb_perf_lock))
perf_unlock(&usb_perf_lock);
}
gser->disabled = !enabled;
- android_enable_function(modem_function, enabled, false);
+ android_enable_function(modem_function, enabled);
return 0;
}
@@ -823,14 +827,14 @@ static int serial_set_enabled(const char
if (!gser)
return 0;
gser->disabled = !enabled;
- android_enable_function(serial_function, enabled, true);
+ android_enable_function(serial_function, enabled);
return 0;
}
static int serial_get_enabled(char *buffer, struct kernel_param *kp)
{
buffer[0] = '0' + !serial_function->hidden;
- printk(KERN_INFO "%s: %d\n", __func__, buffer[0] - '0');
+ /*printk(KERN_INFO "%s: %d\n", __func__, buffer[0] - '0');*/
return 1;
}
module_param_call(serial_enabled, serial_set_enabled, serial_get_enabled, NULL, 0664);
@@ -857,7 +861,9 @@ static struct android_usb_function andro
static int __init init(void)
{
printk(KERN_INFO "serial init\n");
+ wake_lock_init(&vbus_idle_wake_lock, WAKE_LOCK_IDLE, "modem_idle_lock");
perf_lock_init(&usb_perf_lock, PERF_LOCK_HIGHEST, "usb");
+
android_register_function(&android_serial_function);
return 0;
}
file:cf5a2bc77f74aaff7fb388568c0e992fa5d3acb3 -> file:ecb2d35f5dbb84a5e242ec04a5d1ee7fcac93cc8
--- a/drivers/usb/gadget/msm72k_udc.c
+++ b/drivers/usb/gadget/msm72k_udc.c
@@ -49,11 +49,7 @@
#ifdef CONFIG_USB_ACCESSORY_DETECT_BY_ADC
#include <mach/htc_headset_mgr.h>
#endif
-#include <linux/wakelock.h>
-#include <mach/perflock.h>
-
-static struct wake_lock vbus_idle_wake_lock;
-static struct perf_lock usb_perf_lock;
+#include <mach/clk.h>
static const char driver_name[] = "msm72k_udc";
@@ -85,11 +81,14 @@ static struct usb_info *the_usb_info;
static int vbus;
static int use_mfg_serialno;
static char mfg_df_serialno[16];
+static int disable_charger;
-#ifdef CONFIG_USB_ACCESSORY_DETECT
+#if defined (CONFIG_DOCK_ACCESSORY_DETECT) || defined(CONFIG_USB_ACCESSORY_DETECT)
#ifdef CONFIG_USB_ACCESSORY_DETECT_BY_ADC
extern int htc_get_usb_accessory_adc_level(uint32_t *buffer);
#endif
+
+
static struct switch_dev dock_switch = {
.name = "dock",
};
@@ -99,6 +98,12 @@ static struct switch_dev dock_switch = {
#define DOCK_STATE_CAR (1 << 1)
#endif
+#include <linux/wakelock.h>
+#include <mach/perflock.h>
+
+static struct wake_lock vbus_idle_wake_lock;
+static struct perf_lock usb_perf_lock;
+
struct msm_request {
struct usb_request req;
@@ -148,6 +153,10 @@ static void check_charger(struct work_st
#ifdef CONFIG_USB_ACCESSORY_DETECT
static void accessory_detect_work(struct work_struct *w);
#endif
+#ifdef CONFIG_DOCK_ACCESSORY_DETECT
+static void dock_detect_work(struct work_struct *w);
+static void dock_detect_init(struct usb_info *ui);
+#endif
extern int android_switch_function(unsigned func);
extern int android_show_function(char *buf);
extern void android_set_serialno(char *serialno);
@@ -206,6 +215,10 @@ struct usb_info {
void (*phy_reset)(void);
void (*hw_reset)(bool en);
void (*usb_uart_switch)(int);
+ void (*serial_debug_gpios)(int);
+ void (*usb_hub_enable)(bool);
+ int (*china_ac_detect)(void);
+ void (*disable_usb_charger)(void);
/* for notification when USB is connected or disconnected */
void (*usb_connected)(int);
@@ -214,6 +227,7 @@ struct usb_info {
struct work_struct work;
struct delayed_work chg_work;
struct work_struct detect_work;
+ struct work_struct dock_work;
struct work_struct notifier_work;
unsigned phy_status;
unsigned phy_fail_count;
@@ -238,10 +252,13 @@ struct usb_info {
u8 in_lpm;
/* for accessory detection */
+ bool dock_detect;
u8 accessory_detect;
u8 mfg_usb_carkit_enable;
int idpin_irq;
+ int dockpin_irq;
int usb_id_pin_gpio;
+ int dock_pin_gpio;
void (*config_usb_id_gpios)(bool output_enable);
/* 0: none, 1: carkit, 2: usb headset */
u8 accessory_type;
@@ -332,7 +349,7 @@ static int ulpi_write(struct usb_info *u
USB_ULPI_VIEWPORT);
/* wait for completion */
- while((readl(USB_ULPI_VIEWPORT) & ULPI_RUN) && (--timeout)) ;
+ while ((readl(USB_ULPI_VIEWPORT) & ULPI_RUN) && (--timeout)) ;
if (timeout == 0) {
printk(KERN_ERR "ulpi_write: timeout\n");
@@ -812,6 +829,10 @@ static void handle_setup(struct usb_info
case J_TEST:
case K_TEST:
case SE0_NAK_TEST:
+ if (!ui->test_mode) {
+ disable_charger = 1;
+ queue_delayed_work(ui->usb_wq, &ui->chg_work, 0);
+ }
case TST_PKT_TEST:
ui->test_mode = ctl.wIndex;
goto ack;
@@ -1326,13 +1347,17 @@ static ssize_t store_mfg_carkit_enable(s
static DEVICE_ATTR(usb_mfg_carkit_enable, 0644,
show_mfg_carkit_enable, store_mfg_carkit_enable);
+#endif
+#if defined (CONFIG_DOCK_ACCESSORY_DETECT) || defined(CONFIG_USB_ACCESSORY_DETECT)
static ssize_t dock_status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_info *ui = the_usb_info;
if (ui->accessory_type == 1)
return sprintf(buf, "online\n");
+ else if (ui->accessory_type == 3) /*desk dock*/
+ return sprintf(buf, "online\n");
else
return sprintf(buf, "offline\n");
}
@@ -1369,6 +1394,13 @@ static void usb_prepare(struct usb_info
#ifdef CONFIG_USB_ACCESSORY_DETECT
INIT_WORK(&ui->detect_work, accessory_detect_work);
#endif
+#ifdef CONFIG_DOCK_ACCESSORY_DETECT
+ if (ui->dock_detect) {
+ INIT_WORK(&ui->dock_work, dock_detect_work);
+ dock_detect_init(ui);
+ }
+#endif
+
INIT_WORK(&ui->notifier_work, send_usb_connect_notify);
INIT_DELAYED_WORK(&ui->chg_work, check_charger);
@@ -1408,6 +1440,7 @@ static void usb_prepare(struct usb_info
if (ret != 0)
printk(KERN_WARNING "dev_attr_usb_mfg_carkit_enable failed\n");
#endif
+
}
static int usb_wakeup_phy(struct usb_info *ui)
@@ -1550,6 +1583,18 @@ static void usb_start(struct usb_info *u
spin_lock_irqsave(&ui->lock, flags);
ui->flags |= USB_FLAG_START;
+/*if msm_hsusb_set_vbus_state set 1, but usb did not init, the ui =NULL, */
+/*it would cause reboot with usb, it did not swith to USB and ADB fail*/
+/*So when USB start, check again*/
+ if (vbus) {
+ ui->flags |= USB_FLAG_VBUS_ONLINE;
+ } else {
+ ui->flags |= USB_FLAG_VBUS_OFFLINE;
+ }
+ /* online->switch to USB, offline->switch to uart */
+ if (ui->usb_uart_switch)
+ ui->usb_uart_switch(!vbus);
+
queue_work(ui->usb_wq, &ui->work);
spin_unlock_irqrestore(&ui->lock, flags);
}
@@ -1647,6 +1692,77 @@ static void usb_lpm_exit(struct usb_info
}
}
+#ifdef CONFIG_DOCK_ACCESSORY_DETECT
+static irqreturn_t dock_interrupt(int irq, void *data)
+{
+ struct usb_info *ui = data;
+ disable_irq_nosync(ui->dockpin_irq);
+ queue_work(ui->usb_wq, &ui->dock_work);
+ return IRQ_HANDLED;
+}
+static void dock_detect_work(struct work_struct *w)
+{
+ struct usb_info *ui = container_of(w, struct usb_info, dock_work);
+ int value;
+
+ value = gpio_get_value(ui->dock_pin_gpio);
+
+ if (value == 0) {
+ set_irq_type(ui->dockpin_irq, IRQF_TRIGGER_HIGH);
+ switch_set_state(&dock_switch, DOCK_STATE_DESK);
+ ui->accessory_type = 3;
+ printk(KERN_INFO "usb:dock: set state %d\n", DOCK_STATE_DESK);
+ } else {
+ set_irq_type(ui->dockpin_irq, IRQF_TRIGGER_LOW);
+ switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
+ ui->accessory_type = 0;
+ printk(KERN_INFO "usb:dock: set state %d\n", DOCK_STATE_UNDOCKED);
+ }
+ enable_irq(ui->dockpin_irq);
+
+
+}
+static void dock_detect_init(struct usb_info *ui)
+{
+ int ret;
+
+ if (ui->dock_pin_gpio == 0)
+ return;
+ if (ui->dockpin_irq == 0)
+ ui->dockpin_irq = gpio_to_irq(ui->dock_pin_gpio);
+
+ ret = request_irq(ui->dockpin_irq, dock_interrupt,
+ IRQF_TRIGGER_LOW,
+ "dock_irq", ui);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: request_irq failed\n", __func__);
+ return;
+ }
+ printk(KERN_INFO "%s: dock irq %d\n", __func__,
+ ui->dockpin_irq);
+ ret = set_irq_wake(ui->dockpin_irq, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: set_irq_wake failed\n", __func__);
+ goto err;
+ }
+
+ if (switch_dev_register(&dock_switch) < 0) {
+ printk(KERN_ERR "usb: fail to register dock switch!\n");
+ goto err;
+ }
+
+ ret = device_create_file(dock_switch.dev, &dev_attr_status);
+ if (ret != 0)
+ printk(KERN_WARNING "dev_attr_status failed\n");
+
+ return;
+
+err:
+ free_irq(ui->dockpin_irq, 0);
+}
+#endif
+
+
#ifdef CONFIG_USB_ACCESSORY_DETECT
static void carkit_detect(struct usb_info *ui)
{
@@ -1704,7 +1820,7 @@ static void accessory_detect_by_adc(stru
if (adc_value >= 0x2112 && adc_value <= 0x3D53) {
printk(KERN_INFO "usb: headset inserted\n");
ui->accessory_type = 2;
- headset_ext_detect(USB_HEADSET);
+ headset_ext_detect(USB_AUDIO_OUT);
} else if (adc_value >= 0x88A && adc_value <= 0x1E38) {
printk(KERN_INFO "usb: carkit inserted\n");
ui->accessory_type = 1;
@@ -1718,7 +1834,7 @@ static void accessory_detect_by_adc(stru
} else {
if (ui->accessory_type == 2) {
printk(KERN_INFO "usb: headset removed\n");
- headset_ext_detect(NO_DEVICE);
+ headset_ext_detect(USB_NO_HEADSET);
} else if (ui->accessory_type == 1) {
printk(KERN_INFO "usb: carkit removed\n");
switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
@@ -1770,7 +1886,8 @@ static void accessory_detect_init(struct
if (ui->usb_id_pin_gpio == 0)
return;
- ui->idpin_irq = gpio_to_irq(ui->usb_id_pin_gpio);
+ if (ui->idpin_irq == 0)
+ ui->idpin_irq = gpio_to_irq(ui->usb_id_pin_gpio);
ret = request_irq(ui->idpin_irq, usbid_interrupt,
IRQF_TRIGGER_LOW,
@@ -1790,9 +1907,11 @@ static void accessory_detect_init(struct
printk(KERN_ERR "usb: fail to register dock switch!\n");
goto err;
}
+
ret = device_create_file(dock_switch.dev, &dev_attr_status);
if (ret != 0)
printk(KERN_WARNING "dev_attr_status failed\n");
+
return;
err:
free_irq(ui->idpin_irq, 0);
@@ -1825,6 +1944,13 @@ static void charger_detect(struct usb_in
static void check_charger(struct work_struct *w)
{
struct usb_info *ui = container_of(w, struct usb_info, chg_work.work);
+ if (disable_charger) {
+ printk(KERN_INFO "usb: disable charger\n");
+ if (ui->disable_usb_charger)
+ ui->disable_usb_charger();
+ disable_charger = 0;
+ return;
+ }
/* unknown charger */
if (vbus && ui->connect_type == CONNECT_TYPE_UNKNOWN)
queue_work(ui->usb_wq, &ui->notifier_work);
@@ -1836,6 +1962,7 @@ static void usb_do_work(struct work_stru
unsigned long iflags;
unsigned flags, _vbus;
+
for (;;) {
spin_lock_irqsave(&ui->lock, iflags);
flags = ui->flags;
@@ -1852,6 +1979,8 @@ static void usb_do_work(struct work_stru
pr_info("hsusb: IDLE -> ONLINE\n");
usb_lpm_exit(ui);
usb_reset(ui);
+
+ if (!ui->china_ac_detect)
charger_detect(ui);
ui->state = USB_STATE_ONLINE;
@@ -1926,6 +2055,8 @@ static void usb_do_work(struct work_stru
pr_info("hsusb: OFFLINE -> ONLINE\n");
usb_lpm_exit(ui);
usb_reset(ui);
+
+ if (!ui->china_ac_detect)
charger_detect(ui);
ui->state = USB_STATE_ONLINE;
@@ -1944,6 +2075,7 @@ void msm_hsusb_set_vbus_state(int online
{
unsigned long flags = 0;
struct usb_info *ui = the_usb_info;
+ int is_china_ac;
printk(KERN_INFO "%s: %d\n", __func__, online);
if (ui)
@@ -1956,9 +2088,49 @@ void msm_hsusb_set_vbus_state(int online
} else {
ui->flags |= USB_FLAG_VBUS_OFFLINE;
}
- /* online->switch to USB, offline->switch to uart */
- if (ui->usb_uart_switch)
- ui->usb_uart_switch(!online);
+
+ if (online) {
+ if (ui->china_ac_detect) {
+ is_china_ac = ui->china_ac_detect();
+
+ if (is_china_ac) {
+ ui->connect_type = CONNECT_TYPE_AC;
+ queue_work(ui->usb_wq, &ui->notifier_work);
+ usb_lpm_enter(ui);
+ printk(KERN_INFO "usb: AC charger\n");
+ } else {
+ ui->connect_type = CONNECT_TYPE_UNKNOWN;
+ queue_delayed_work(ui->usb_wq, &ui->chg_work,
+ DELAY_FOR_CHECK_CHG);
+ printk(KERN_INFO "usb: not AC charger\n");
+ }
+ }
+
+
+ /*set uart to gpo*/
+ if (ui->serial_debug_gpios)
+ ui->serial_debug_gpios(0);
+ /*turn on USB HUB*/
+ if (ui->usb_hub_enable) {
+ ui->usb_hub_enable(1);
+ }
+
+ /*USB*/
+ if (ui->usb_uart_switch)
+ ui->usb_uart_switch(0);
+ } else {
+ /*turn off USB HUB*/
+ if (ui->usb_hub_enable)
+ ui->usb_hub_enable(0);
+
+ /*UART*/
+ if (ui->usb_uart_switch)
+ ui->usb_uart_switch(1);
+ /*configure uart pin to alternate function*/
+ if (ui->serial_debug_gpios)
+ ui->serial_debug_gpios(1);
+ }
+
queue_work(ui->usb_wq, &ui->work);
}
}
@@ -2379,6 +2551,10 @@ static int msm72k_probe(struct platform_
ui->phy_init_seq = pdata->phy_init_seq;
ui->usb_connected = pdata->usb_connected;
ui->usb_uart_switch = pdata->usb_uart_switch;
+ ui->serial_debug_gpios = pdata->serial_debug_gpios;
+ ui->usb_hub_enable = pdata->usb_hub_enable;
+ ui->china_ac_detect = pdata->china_ac_detect;
+ ui->disable_usb_charger = pdata->disable_usb_charger;
ui->accessory_detect = pdata->accessory_detect;
printk(KERN_INFO "usb: accessory detect %d\n",
@@ -2386,6 +2562,15 @@ static int msm72k_probe(struct platform_
ui->usb_id_pin_gpio = pdata->usb_id_pin_gpio;
printk(KERN_INFO "usb: id_pin_gpio %d\n",
pdata->usb_id_pin_gpio);
+
+ ui->dock_detect = pdata->dock_detect;
+ printk(KERN_INFO "usb: dock detect %d\n",
+ ui->dock_detect);
+ ui->dock_pin_gpio = pdata->dock_pin_gpio;
+ printk(KERN_INFO "usb: dock pin gpio %d\n",
+ ui->dock_pin_gpio);
+
+ ui->idpin_irq = pdata->id_pin_irq;
if (pdata->config_usb_id_gpios)
ui->config_usb_id_gpios = pdata->config_usb_id_gpios;
}
@@ -2475,8 +2660,7 @@ static int msm72k_probe(struct platform_
use_mfg_serialno = 1;
wake_lock_init(&vbus_idle_wake_lock, WAKE_LOCK_IDLE, "usb_idle_lock");
perf_lock_init(&usb_perf_lock, PERF_LOCK_HIGHEST, "usb");
- }
- else
+ } else
use_mfg_serialno = 0;
strncpy(mfg_df_serialno, "000000000000", strlen("000000000000"));
file:33ac6acbdb780f0886a546fc3b31ed5dd9ab31ef -> file:48267bc0b2e00c151bf05e8ed6caa2662e1de9a5
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -291,13 +291,9 @@ gen_ndis_query_resp (int configNr, u32 O
/* mandatory */
case OID_GEN_VENDOR_DESCRIPTION:
pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
- if ( rndis_per_dev_params [configNr].vendorDescr ) {
- length = strlen (rndis_per_dev_params [configNr].vendorDescr);
- memcpy (outbuf,
- rndis_per_dev_params [configNr].vendorDescr, length);
- } else {
- outbuf[0] = 0;
- }
+ length = strlen (rndis_per_dev_params [configNr].vendorDescr);
+ memcpy (outbuf,
+ rndis_per_dev_params [configNr].vendorDescr, length);
retval = 0;
break;
file:a082dd5a3e9f19546a25d208b919b920e7004ac3 -> file:48b9ccbefcc901d74d2d5294255750a0c45c9a95
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+//#define DEBUG
/* #define VERBOSE_DEBUG */
#include <linux/kernel.h>
@@ -54,6 +55,10 @@
#define UETH__VERSION "29-May-2008"
+/***********************************************************************/
+#define LOG_TAG1 "[ETH] "
+
+/***********************************************************************/
struct eth_dev {
/* lock is held while accessing port_usb
* or updating its backlink port_usb->ioport
@@ -94,7 +99,8 @@ struct eth_dev {
#ifdef CONFIG_USB_GADGET_DUALSPEED
-static unsigned qmult = 5;
+//static unsigned qmult = 5;
+static unsigned qmult = 12;
module_param(qmult, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(qmult, "queue length multiplier at high speed");
@@ -241,7 +247,7 @@ rx_submit(struct eth_dev *dev, struct us
skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
if (skb == NULL) {
- DBG(dev, "no rx skb\n");
+ DBG(dev, LOG_TAG1 "no rx skb\n");
goto enomem;
}
@@ -261,7 +267,7 @@ rx_submit(struct eth_dev *dev, struct us
enomem:
defer_kevent(dev, WORK_RX_MEMORY);
if (retval) {
- DBG(dev, "rx submit --> %d\n", retval);
+ DBG(dev, LOG_TAG1 "rx submit --> %d\n", retval);
if (skb)
dev_kfree_skb_any(skb);
spin_lock_irqsave(&dev->req_lock, flags);
@@ -308,7 +314,7 @@ static void rx_complete(struct usb_ep *e
|| skb2->len > ETH_FRAME_LEN) {
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
- DBG(dev, "rx length %d\n", skb2->len);
+ DBG(dev, LOG_TAG1 "rx length %d\n", skb2->len);
dev_kfree_skb_any(skb2);
goto next_frame;
}
@@ -320,6 +326,8 @@ static void rx_complete(struct usb_ep *e
* use skb buffers.
*/
status = netif_rx(skb2);
+ if (status != NET_RX_SUCCESS)
+ DBG(dev, LOG_TAG1 "%s@%d status=%d", __func__, __LINE__, status);
next_frame:
skb2 = skb_dequeue(&dev->rx_frames);
}
@@ -328,12 +336,12 @@ next_frame:
/* software-driven interface shutdown */
case -ECONNRESET: /* unlink */
case -ESHUTDOWN: /* disconnect etc */
- VDBG(dev, "rx shutdown, code %d\n", status);
+ VDBG(dev, LOG_TAG1 "rx shutdown, code %d\n", status);
goto quiesce;
/* for hardware automagic (such as pxa) */
case -ECONNABORTED: /* endpoint reset */
- DBG(dev, "rx %s reset\n", ep->name);
+ DBG(dev, LOG_TAG1 "rx %s reset\n", ep->name);
defer_kevent(dev, WORK_RX_MEMORY);
quiesce:
dev_kfree_skb_any(skb);
@@ -346,7 +354,7 @@ quiesce:
default:
dev->net->stats.rx_errors++;
- DBG(dev, "rx status %d\n", status);
+ DBG(dev, LOG_TAG1 "rx status %d\n", status);
break;
}
@@ -380,7 +388,10 @@ static int prealloc(struct list_head *li
while (i--) {
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (!req)
+ {
+ printk(KERN_ERR "%s@%d: usb_ep_alloc_request fail: %d\n", __func__, __LINE__, i);
return list_empty(list) ? -ENOMEM : 0;
+ }
list_add(&req->list, list);
}
return 0;
@@ -409,10 +420,16 @@ static int alloc_requests(struct eth_dev
spin_lock(&dev->req_lock);
status = prealloc(&dev->tx_reqs, link->in_ep, n);
if (status < 0)
+ {
+ ERROR(dev, "fail to alloc in_ep\n");
goto fail;
+ }
status = prealloc(&dev->rx_reqs, link->out_ep, n);
if (status < 0)
+ {
+ ERROR(dev, "fail to alloc out_ep\n");
goto fail;
+ }
goto done;
fail:
DBG(dev, "can't alloc requests\n");
@@ -545,6 +562,7 @@ static netdev_tx_t eth_start_xmit(struct
* network stack decided to xmit but before we got the spinlock.
*/
if (list_empty(&dev->tx_reqs)) {
+ DBG(dev, LOG_TAG1 "%s@%d: tx_reqs empty, NETDEV_TX_BUSY\n", __func__, __LINE__);
spin_unlock_irqrestore(&dev->req_lock, flags);
return NETDEV_TX_BUSY;
}
@@ -554,7 +572,10 @@ static netdev_tx_t eth_start_xmit(struct
/* temporarily stop TX queue when the freelist empties */
if (list_empty(&dev->tx_reqs))
+ {
+ DBG(dev, LOG_TAG1 "%s@%d: tx_reqs empty, netif_stop_queue\n", __func__, __LINE__);
netif_stop_queue(net);
+ }
spin_unlock_irqrestore(&dev->req_lock, flags);
/* no buffer copies needed, unless the network stack did it
@@ -609,7 +630,10 @@ drop:
dev->net->stats.tx_dropped++;
spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs))
+ {
+ DBG(dev, LOG_TAG1 "%s@%d: tx_reqs empty, netif_start_queue\n", __func__, __LINE__);
netif_start_queue(net);
+ }
list_add(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->req_lock, flags);
}
@@ -765,8 +789,11 @@ int __init gether_setup(struct usb_gadge
struct net_device *net;
int status;
- if (the_dev)
+ if (the_dev) {
+ if (ethaddr)
+ memcpy(ethaddr, the_dev->host_mac, ETH_ALEN);
return -EBUSY;
+ }
net = alloc_etherdev(sizeof *dev);
if (!net)
@@ -889,7 +916,7 @@ struct net_device *gether_connect(struct
if (result == 0) {
dev->zlp = link->is_zlp_ok;
- DBG(dev, "qlen %d\n", qlen(dev->gadget));
+ DBG(dev, LOG_TAG1 "qlen %d\n", qlen(dev->gadget));
dev->header_len = link->header_len;
dev->unwrap = link->unwrap;
@@ -941,6 +968,7 @@ void gether_disconnect(struct gether *li
struct eth_dev *dev = link->ioport;
struct usb_request *req;
+ /* WARN_ON(!dev); */
if (!dev)
return;
file:f8e70223af4fae6bca555caf1a66b0b524bced27 -> file:40abba500d79b509d1b6721e95ddb8707009317a
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -28,7 +28,6 @@
#include "u_serial.h"
-
/*
* This component encapsulates the TTY layer glue needed to provide basic
* "serial port" functionality through the USB gadget stack. Each such
@@ -77,9 +76,12 @@
* next layer of buffering. For TX that's a circular buffer; for RX
* consider it a NOP. A third layer is provided by the TTY code.
*/
-#define QUEUE_SIZE 16
+#define QUEUE_SIZE 32
+#define RX_QUEUE_SIZE 96
#define WRITE_BUF_SIZE 8192 /* TX only */
+bool MODEM_DEBUG_ON;
+
static struct workqueue_struct *gs_tty_wq;
/* circular buffer */
@@ -496,7 +498,9 @@ static void gs_rx_push(struct work_struc
/* hand any queued data to the tty */
spin_lock_irq(&port->port_lock);
+
tty = port->port_tty;
+
while (!list_empty(queue)) {
struct usb_request *req;
@@ -506,26 +510,6 @@ static void gs_rx_push(struct work_struc
if (!tty)
goto recycle;
- /* leave data queued if tty was rx throttled */
- if (test_bit(TTY_THROTTLED, &tty->flags))
- break;
-
- switch (req->status) {
- case -ESHUTDOWN:
- disconnect = true;
- pr_vdebug(PREFIX "%d: shutdown\n", port->port_num);
- break;
-
- default:
- /* presumably a transient fault */
- pr_warning(PREFIX "%d: unexpected RX status %d\n",
- port->port_num, req->status);
- /* FALLTHROUGH */
- case 0:
- /* normal completion */
- break;
- }
-
/* push data to (open) tty */
if (req->actual) {
char *packet = req->buf;
@@ -539,18 +523,23 @@ static void gs_rx_push(struct work_struc
packet += n;
size -= n;
}
- pr_vdebug(PREFIX "%d: tty_insert %d\n", port->port_num,
- size);
+
+ if (MODEM_DEBUG_ON)
+ printk("%d: tty_insert %d\n", port->port_num, size);
+
count = tty_insert_flip_string(tty, packet, size);
if (count)
do_push = true;
if (count != size) {
/* stop pushing; TTY layer can't handle more */
port->n_read += count;
- pr_vdebug(PREFIX "%d: rx block %d/%d\n",
- port->port_num,
- count, req->actual);
- break;
+ if (MODEM_DEBUG_ON) {
+ printk("%d: rx block %d/%d\n",
+ port->port_num,
+ count, req->actual);
+ list_move(&req->list, &port->read_pool);
+ break;
+ }
}
port->n_read = 0;
}
@@ -561,7 +550,7 @@ recycle:
/* Push from tty to ldisc; this is immediate with low_latency, and
* may trigger callbacks to this driver ... so drop the spinlock.
*/
- if (tty && do_push) {
+ if ((tty && do_push)) {
spin_unlock_irq(&port->port_lock);
tty_flip_buffer_push(tty);
wake_up_interruptible(&tty->read_wait);
@@ -599,22 +588,61 @@ recycle:
static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct gs_port *port = ep->driver_data;
- unsigned long flags;
- pr_vdebug("%s: %d bytes\n", __func__, req->actual);
+ /* used global variable */
+ struct gs_port *port = ep->driver_data;
+ struct tty_struct *tty;
- /* Queue all received data until the tty layer is ready for it. */
- spin_lock_irqsave(&port->port_lock, flags);
- list_add_tail(&req->list, &port->read_queue);
- queue_work(gs_tty_wq, &port->push_work);
- spin_unlock_irqrestore(&port->port_lock, flags);
+ tty = port->port_tty;
+ if (tty == NULL) {
+ printk(KERN_ERR "port_tty NULL\n");
+ return;
+ }
+
+ if (MODEM_DEBUG_ON)
+ printk("%s: %d bytes\n", __func__, req->actual);
+
+ switch (req->status) {
+ case 0:
+ spin_lock(&port->port_lock);
+ if (!test_bit(TTY_THROTTLED, &tty->flags)) {
+ list_add_tail(&req->list, &port->read_queue);
+ queue_work(gs_tty_wq, &port->push_work);
+ } else {
+ printk("%s: TTY_THROTTLED\n", __func__);
+ list_add_tail(&req->list, &port->read_queue);
+ }
+ spin_unlock(&port->port_lock);
+ break;
+ case -ESHUTDOWN:
+ /* disconnect */
+ printk("%s: ESHUTDOWN\n", __func__);
+ break;
+ case -ENODEV:
+ spin_lock(&port->port_lock);
+ printk("%s: ENODEV\n", __func__);
+ list_add_tail(&req->list, &port->read_pool);
+ /* Implemented handling in future if needed */
+ spin_unlock(&port->port_lock);
+ break;
+ default:
+ spin_lock(&port->port_lock);
+ list_add_tail(&req->list, &port->read_pool);
+ printk(KERN_ERR
+ "gs_read_complete: unexpected status error, status=%d\n",
+ req->status);
+ spin_unlock(&port->port_lock);
+ /* goto requeue; */
+ break;
+ }
}
static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
{
struct gs_port *port = ep->driver_data;
unsigned long flags;
- pr_vdebug("%s: %d bytes\n", __func__, req->actual);
+
+ if (MODEM_DEBUG_ON)
+ printk("%s: %d bytes\n", __func__, req->actual);
spin_lock_irqsave(&port->port_lock, flags);
list_add(&req->list, &port->write_pool);
@@ -652,7 +680,7 @@ static void gs_free_requests(struct usb_
}
static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
- void (*fn)(struct usb_ep *, struct usb_request *))
+ void (*fn)(struct usb_ep *, struct usb_request *), int size)
{
int i;
struct usb_request *req;
@@ -661,7 +689,7 @@ static int gs_alloc_requests(struct usb_
* do quite that many this time, don't fail ... we just won't
* be as speedy as we might otherwise be.
*/
- for (i = 0; i < QUEUE_SIZE; i++) {
+ for (i = 0; i < size; i++) {
req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
if (!req)
return list_empty(head) ? -ENOMEM : 0;
@@ -693,12 +721,12 @@ static int gs_start_io(struct gs_port *p
* configurations may use different endpoints with a given port;
* and high speed vs full speed changes packet sizes too.
*/
- status = gs_alloc_requests(ep, head, gs_read_complete);
+ status = gs_alloc_requests(ep, head, gs_read_complete, RX_QUEUE_SIZE);
if (status)
return status;
status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
- gs_write_complete);
+ gs_write_complete, QUEUE_SIZE);
if (status) {
gs_free_requests(ep, head);
return status;
@@ -1007,7 +1035,8 @@ static void gs_unthrottle(struct tty_str
* read queue backs up enough we'll be NAKing OUT packets.
*/
queue_work(gs_tty_wq, &port->push_work);
- pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num);
+ if (MODEM_DEBUG_ON)
+ printk("%d: unthrottle\n", port->port_num);
}
spin_unlock_irqrestore(&port->port_lock, flags);
}
@@ -1174,6 +1203,9 @@ int gserial_setup(struct usb_gadget *g,
if (count == 0 || count > N_PORTS)
return -EINVAL;
+ if (gs_tty_driver)
+ return -EBUSY;
+
gs_tty_wq = create_singlethread_workqueue("gs_tty");
if (gs_tty_wq == 0)
return -ENOMEM;
@@ -1418,9 +1450,9 @@ void gserial_disconnect(struct gserial *
/* REVISIT as above: how best to track this? */
port->port_line_coding = gser->port_line_coding;
-#if 0
port->port_usb = NULL;
gser->ioport = NULL;
+#if 0
if (port->open_count > 0 || port->openclose) {
wake_up_interruptible(&port->drain_wait);
if (port->port_tty)
@@ -1447,3 +1479,14 @@ void gserial_disconnect(struct gserial *
gs_free_requests(gser->in, &port->write_pool);
spin_unlock_irqrestore(&port->port_lock, flags);
}
+
+static int modem_debug_enabled(const char *val, struct kernel_param *kp)
+{
+ int enabled = simple_strtol(val, NULL, 0);
+
+ MODEM_DEBUG_ON = (enabled) ? true : false;
+ return 0;
+}
+
+module_param_call(modem_debug, modem_debug_enabled, NULL, NULL, 0664);
+
file:50a5d12bc3ec70ac3ab14abcab45bed50238e6cb -> file:0c4e7836464be461217e9352d2f29be51e34784c
--- a/include/linux/usb/android_composite.h
+++ b/include/linux/usb/android_composite.h
@@ -89,9 +89,10 @@ extern void android_usb_set_connected(in
extern void android_register_function(struct android_usb_function *f);
-extern void android_enable_function(struct usb_function *f, int enable, bool reset);
+extern void android_enable_function(struct usb_function *f, int enable);
extern int android_get_model_id(void);
+extern int android_switch_function(unsigned func);
#endif /* __LINUX_USB_ANDROID_H */
file:062f1d671d58c2900065ce1d6075816155c281de -> file:66884030c58aeb8eefa36dbce95318164c1cf8da
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -284,8 +284,7 @@ struct usb_composite_driver {
void (*suspend)(struct usb_composite_dev *);
void (*resume)(struct usb_composite_dev *);
- void (*enable_function)(struct usb_function *f, int enable, bool reset);
-
+ void (*enable_function)(struct usb_function *f, int enable);
};
extern int usb_composite_register(struct usb_composite_driver *);
file:dd0bde120045aab26a2ce403af9d39d8b46b4171 -> file:2526f3bbd273e522e1ff77b2ba404c87d9a5a56a
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -19,8 +19,4 @@
/* device can't handle its Configuration or Interface strings */
#define USB_QUIRK_CONFIG_INTF_STRINGS 0x00000008
-/* device needs a pause during initialization, after we read the device
- descriptor */
-#define USB_QUIRK_DELAY_INIT 0x00000040
-
#endif /* __LINUX_USB_QUIRKS_H */