drivers: usb: gadget: update some usb drivers for USB Tethering.
This commit is contained in:
parent
9bb78d2a7f
commit
560a956cd5
@ -129,6 +129,45 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* dma_coherent_pre_ops - barrier functions for coherent memory before DMA.
|
||||
* A barrier is required to ensure memory operations are complete before the
|
||||
* initiation of a DMA xfer.
|
||||
* If the coherent memory is Strongly Ordered
|
||||
* - pre ARMv7 and 8x50 guarantees ordering wrt other mem accesses
|
||||
* - ARMv7 guarantees ordering only within a 1KB block, so we need a barrier
|
||||
* If coherent memory is normal then we need a barrier to prevent
|
||||
* reordering
|
||||
*/
|
||||
static inline void dma_coherent_pre_ops(void)
|
||||
{
|
||||
#if (__LINUX_ARM_ARCH__ >= 7)
|
||||
dmb();
|
||||
#else
|
||||
if (arch_is_coherent())
|
||||
dmb();
|
||||
else
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* dma_post_coherent_ops - barrier functions for coherent memory after DMA.
|
||||
* If the coherent memory is Strongly Ordered we dont need a barrier since
|
||||
* there are no speculative fetches to Strongly Ordered memory.
|
||||
* If coherent memory is normal then we need a barrier to prevent reordering
|
||||
*/
|
||||
static inline void dma_coherent_post_ops(void)
|
||||
{
|
||||
#if (__LINUX_ARM_ARCH__ >= 7)
|
||||
dmb();
|
||||
#else
|
||||
if (arch_is_coherent())
|
||||
dmb();
|
||||
else
|
||||
barrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_alloc_coherent - allocate consistent memory for DMA
|
||||
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
|
||||
|
@ -179,6 +179,16 @@ enum {
|
||||
};
|
||||
|
||||
void msm_hsusb_set_vbus_state(int online);
|
||||
enum usb_connect_type {
|
||||
CONNECT_TYPE_CLEAR = -2,
|
||||
CONNECT_TYPE_UNKNOWN = -1,
|
||||
CONNECT_TYPE_NONE = 0,
|
||||
CONNECT_TYPE_USB,
|
||||
CONNECT_TYPE_AC,
|
||||
CONNECT_TYPE_9V_AC,
|
||||
CONNECT_TYPE_WIRELESS,
|
||||
CONNECT_TYPE_INTERNAL,
|
||||
};
|
||||
|
||||
#define MSM_MAX_DEC_CNT 14
|
||||
/* 7k target ADSP information */
|
||||
|
@ -47,8 +47,18 @@ struct msm_hsusb_platform_data {
|
||||
/* 1 : uart, 0 : usb */
|
||||
void (*usb_uart_switch)(int);
|
||||
void (*config_usb_id_gpios)(bool enable);
|
||||
/* val, reg pairs terminated by -1 */
|
||||
int *phy_init_seq;
|
||||
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;
|
||||
void (*change_phy_voltage)(int);
|
||||
int (*ldo_init) (int init);
|
||||
int (*ldo_enable) (int enable);
|
||||
int (*rpc_connect)(int);
|
||||
/* 1 : mhl, 0 : usb */
|
||||
void (*usb_mhl_switch)(bool);
|
||||
|
||||
#ifdef CONFIG_USB_FUNCTION
|
||||
/* USB device descriptor fields */
|
||||
@ -74,10 +84,15 @@ struct msm_hsusb_platform_data {
|
||||
int num_products;
|
||||
struct msm_hsusb_product *products;
|
||||
#endif
|
||||
char *serial_number;
|
||||
int usb_id_pin_gpio;
|
||||
bool enable_car_kit_detect;
|
||||
__u8 accessory_detect;
|
||||
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 ac_9v_gpio;
|
||||
};
|
||||
|
||||
int usb_get_connect_type(void);
|
||||
|
@ -37,11 +37,30 @@
|
||||
do { } while (0)
|
||||
#endif /* VERBOSE */
|
||||
|
||||
#ifndef __LINUX_USB_COMPOSITE_H
|
||||
#define ERROR(fmt,args...) \
|
||||
xprintk(KERN_ERR , fmt , ## args)
|
||||
#define INFO(fmt,args...) \
|
||||
xprintk(KERN_INFO , fmt , ## args)
|
||||
#endif
|
||||
|
||||
#define USB_ERR(fmt, args...) \
|
||||
printk(KERN_ERR "[USB:ERR] " fmt, ## args)
|
||||
#define USB_WARNING(fmt, args...) \
|
||||
printk(KERN_WARNING "[USB] " fmt, ## args)
|
||||
#define USB_INFO(fmt, args...) \
|
||||
printk(KERN_INFO "[USB] " fmt, ## args)
|
||||
#define USB_DEBUG(fmt, args...) \
|
||||
printk(KERN_DEBUG "[USB] " fmt, ## args)
|
||||
|
||||
#define USBH_ERR(fmt, args...) \
|
||||
printk(KERN_ERR "[USBH:ERR] " fmt, ## args)
|
||||
#define USBH_WARNING(fmt, args...) \
|
||||
printk(KERN_WARNING "[USBH] " fmt, ## args)
|
||||
#define USBH_INFO(fmt, args...) \
|
||||
printk(KERN_INFO "[USBH] " fmt, ## args)
|
||||
#define USBH_DEBUG(fmt, args...) \
|
||||
printk(KERN_DEBUG "[USBH] " fmt, ## args)
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
@ -51,9 +70,12 @@
|
||||
#define USB_HWDEVICE (MSM_USB_BASE + 0x000C)
|
||||
#define USB_HWTXBUF (MSM_USB_BASE + 0x0010)
|
||||
#define USB_HWRXBUF (MSM_USB_BASE + 0x0014)
|
||||
#define USB_AHBBURST (MSM_USB_BASE + 0x0090)
|
||||
#define USB_AHBMODE (MSM_USB_BASE + 0x0098)
|
||||
#define USB_AHB_BURST (MSM_USB_BASE + 0x0090)
|
||||
#define USB_AHB_MODE (MSM_USB_BASE + 0x0098)
|
||||
#define USB_AHBBURST (USB_AHB_BURST)
|
||||
#define USB_AHBMODE (USB_AHB_MODE)
|
||||
#define USB_SBUSCFG (MSM_USB_BASE + 0x0090)
|
||||
#define USB_ROC_AHB_MODE (MSM_USB_BASE + 0x0090)
|
||||
|
||||
#define USB_CAPLENGTH (MSM_USB_BASE + 0x0100) /* 8 bit */
|
||||
#define USB_HCIVERSION (MSM_USB_BASE + 0x0102) /* 16 bit */
|
||||
@ -82,12 +104,26 @@
|
||||
#define USB_ENDPTCTRL(n) (MSM_USB_BASE + 0x01C0 + (4 * (n)))
|
||||
|
||||
|
||||
#define USBCMD_RESET 2
|
||||
#define USBCMD_ATTACH 1
|
||||
#define USBCMD_ATDTW (1 << 14)
|
||||
#define USBCMD_RESET 2
|
||||
#define USBCMD_ATTACH 1
|
||||
#define USBCMD_RS (1 << 0) /* run/stop bit */
|
||||
#define USBCMD_ATDTW (1 << 14)
|
||||
|
||||
#define ASYNC_INTR_CTRL (1 << 29)
|
||||
#define ULPI_STP_CTRL (1 << 30)
|
||||
#define USBCMD_ITC(n) (n << 16)
|
||||
#define USBCMD_ITC_MASK (0xFF << 16)
|
||||
|
||||
|
||||
#define USBMODE_DEVICE 2
|
||||
#define USBMODE_HOST 3
|
||||
/* Redefining SDIS bit as it defined incorrectly in ehci.h. */
|
||||
#ifdef USBMODE_SDIS
|
||||
#undef USBMODE_SDIS
|
||||
#endif
|
||||
#define USBMODE_SDIS (1 << 4) /* stream disable */
|
||||
#define USBMODE_VBUS (1 << 5) /* vbus power select */
|
||||
|
||||
|
||||
struct ept_queue_head {
|
||||
unsigned config;
|
||||
@ -138,7 +174,7 @@ struct ept_queue_item {
|
||||
#define STS_NAKI (1 << 16) /* */
|
||||
#define STS_SLI (1 << 8) /* R/WC - suspend state entered */
|
||||
#define STS_SRI (1 << 7) /* R/WC - SOF recv'd */
|
||||
#define STS_URI (1 << 6) /* R/WC - RESET recv'd - write to clear */
|
||||
#define STS_URI (1 << 6) /* R/WC - RESET recv'd */
|
||||
#define STS_FRI (1 << 3) /* R/WC - Frame List Rollover */
|
||||
#define STS_PCI (1 << 2) /* R/WC - Port Change Detect */
|
||||
#define STS_UEI (1 << 1) /* R/WC - USB Error */
|
||||
@ -175,6 +211,38 @@ struct ept_queue_item {
|
||||
#define CTRL_RXT_INT (3 << 2)
|
||||
#define CTRL_RXT_EP_TYPE_SHIFT 2
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
|
||||
#define ULPI_DIGOUT_CTRL 0X36
|
||||
#define ULPI_CDR_AUTORESET (1 << 1)
|
||||
#else
|
||||
#define ULPI_DIGOUT_CTRL 0X31
|
||||
#define ULPI_CDR_AUTORESET (1 << 5)
|
||||
#endif
|
||||
|
||||
#define ULPI_FUNC_CTRL_CLR (0x06)
|
||||
#define ULPI_IFC_CTRL_CLR (0x09)
|
||||
#define ULPI_AMPLITUDE_MAX (0x0C)
|
||||
#define ULPI_OTG_CTRL (0x0B)
|
||||
#define ULPI_OTG_CTRL_CLR (0x0C)
|
||||
#define ULPI_INT_RISE_CLR (0x0F)
|
||||
#define ULPI_INT_FALL_CLR (0x12)
|
||||
#define ULPI_DEBUG_REG (0x15)
|
||||
#define ULPI_SCRATCH_REG (0x16)
|
||||
#define ULPI_CONFIG_REG1 (0x30)
|
||||
#define ULPI_CONFIG_REG2 (0X31)
|
||||
#define ULPI_CONFIG_REG (0x31)
|
||||
#define ULPI_CONFIG_REG3 (0X32)
|
||||
#define ULPI_CHG_DETECT_REG (0x34)
|
||||
#define ULPI_PRE_EMPHASIS_MASK (3 << 4)
|
||||
#define ULPI_DRV_AMPL_MASK (3 << 2)
|
||||
#define ULPI_ONCLOCK (1 << 6)
|
||||
#define ULPI_FUNC_SUSPENDM (1 << 6)
|
||||
#define ULPI_IDPU (1 << 0)
|
||||
#define ULPI_HOST_DISCONNECT (1 << 0)
|
||||
#define ULPI_VBUS_VALID (1 << 1)
|
||||
#define ULPI_SE1_GATE (1 << 2)
|
||||
#define ULPI_SESS_END (1 << 3)
|
||||
#define ULPI_ID_GND (1 << 4)
|
||||
#define ULPI_WAKEUP (1 << 31)
|
||||
#define ULPI_RUN (1 << 30)
|
||||
#define ULPI_WRITE (1 << 29)
|
||||
@ -184,12 +252,17 @@ struct ept_queue_item {
|
||||
#define ULPI_DATA(n) ((n) & 255)
|
||||
#define ULPI_DATA_READ(n) (((n) >> 8) & 255)
|
||||
|
||||
#define ULPI_DEBUG_REG (0x15)
|
||||
#define ULPI_SCRATCH_REG (0x16)
|
||||
/* control charger detection by ULPI or externally */
|
||||
#define ULPI_EXTCHGCTRL_65NM (1 << 2)
|
||||
#define ULPI_EXTCHGCTRL_180NM (1 << 3)
|
||||
|
||||
#define ULPI_FUNC_CTRL_CLR (0x06)
|
||||
#define ULPI_FUNC_SUSPENDM (1 << 6)
|
||||
/* charger detection power on control */
|
||||
#define ULPI_CHGDETON (1 << 1)
|
||||
|
||||
/* enable charger detection */
|
||||
#define ULPI_CHGDETEN (1 << 0)
|
||||
#define ULPI_CHGTYPE_65NM (1 << 3)
|
||||
#define ULPI_CHGTYPE_180NM (1 << 4)
|
||||
|
||||
/* USB_PORTSC bits for determining port speed */
|
||||
#define PORTSC_PSPD_FS (0 << 26)
|
||||
@ -218,6 +291,30 @@ struct ept_queue_item {
|
||||
#define PORTSC_FPR (1 << 6) /* R/W - State normal => suspend */
|
||||
#define PORTSC_SUSP (1 << 7) /* Read - Port in suspend state */
|
||||
#define PORTSC_LS (3 << 10) /* Read - Port's Line status */
|
||||
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
|
||||
#define PORTSC_CCS (1 << 0) /* current connect status */
|
||||
#define PORTSC_PTS (3 << 30)
|
||||
#define PORTSC_PTS_ULPI (2 << 30)
|
||||
#define PORTSC_PTS_SERIAL (3 << 30)
|
||||
|
||||
#define PORTSC_PORT_SPEED_FULL 0x00000000
|
||||
#define PORTSC_PORT_SPEED_LOW 0x04000000
|
||||
#define PORTSC_PORT_SPEED_HIGH 0x08000000
|
||||
#define PORTSC_PORT_SPEED_MASK 0x0c000000
|
||||
|
||||
#define SBUSCFG_AHBBRST_INCR4 0x01
|
||||
#define ULPI_USBINTR_ENABLE_FALLING_S 0x11
|
||||
#define ULPI_USBINTR_ENABLE_FALLING_C 0x12
|
||||
#define ULPI_USBINTR_STATUS 0x13
|
||||
#define ULPI_USBINTR_ENABLE_RASING_S 0x0E
|
||||
#define ULPI_USBINTR_ENABLE_RASING_C 0x0F
|
||||
#define ULPI_SESSION_END_RAISE (1 << 3)
|
||||
#define ULPI_SESSION_END_FALL (1 << 3)
|
||||
#define ULPI_SESSION_VALID_RAISE (1 << 2)
|
||||
#define ULPI_SESSION_VALID_FALL (1 << 2)
|
||||
#define ULPI_VBUS_VALID_RAISE (1 << 1)
|
||||
#define ULPI_VBUS_VALID_FALL (1 << 1)
|
||||
|
||||
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
|
||||
#define PORTSC_CCS (1 << 0) /* current connect status */
|
||||
#define PORTSC_PTS (3 << 30)
|
||||
@ -238,6 +335,9 @@ struct ept_queue_item {
|
||||
#define PORTSC_PTC_SE0_NAK (0x03 << 16)
|
||||
#define PORTSC_PTC_TST_PKT (0x04 << 16)
|
||||
|
||||
#define USBH (1 << 15)
|
||||
#define USB_PHY (1 << 18)
|
||||
|
||||
#define PORTSC_PTS_MASK (3 << 30)
|
||||
#define PORTSC_PTS_ULPI (2 << 30)
|
||||
#define PORTSC_PTS_SERIAL (3 << 30)
|
||||
@ -250,5 +350,9 @@ struct ept_queue_item {
|
||||
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
|
||||
|
||||
#define ULPI_DEBUG 0x15
|
||||
#define ULPI_CLOCK_SUSPENDM (1 << 3)
|
||||
#define ULPI_SUSPENDM (1 << 6)
|
||||
#endif /* _USB_FUNCTION_MSM_HSUSB_HW_H */
|
||||
#define ULPI_CALIB_STS (1 << 7)
|
||||
#define ULPI_CALIB_VAL(x) (x & 0x7C)
|
||||
|
||||
#endif /* __LINUX_USB_GADGET_MSM72K_UDC_H__ */
|
||||
|
@ -21,11 +21,11 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/usb/android_composite.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
@ -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,
|
||||
@ -478,11 +482,14 @@ int android_switch_function(unsigned func)
|
||||
dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_MSM_72K
|
||||
/* avoid sending a disconnect switch event until after we disconnect */
|
||||
msm_hsusb_request_reset();
|
||||
#else
|
||||
/* force reenumeration */
|
||||
if (dev->cdev && dev->cdev->gadget &&
|
||||
dev->cdev->gadget->speed != USB_SPEED_UNKNOWN) {
|
||||
|
||||
/* avoid sending a disconnect switch event until after we disconnect */
|
||||
usb_gadget_disconnect(dev->cdev->gadget);
|
||||
msleep(10);
|
||||
usb_gadget_connect(dev->cdev->gadget);
|
||||
@ -500,6 +507,7 @@ void android_enable_function(struct usb_function *f, int enable)
|
||||
if (!!f->hidden != disable) {
|
||||
f->hidden = disable;
|
||||
|
||||
|
||||
#ifdef CONFIG_USB_ANDROID_RNDIS
|
||||
if (!strcmp(f->name, "rndis")) {
|
||||
struct usb_function *func;
|
||||
@ -565,6 +573,9 @@ static int __init android_probe(struct platform_device *pdev)
|
||||
|
||||
printk(KERN_INFO "android_probe pdata: %p\n", pdata);
|
||||
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
if (pdata) {
|
||||
dev->products = pdata->products;
|
||||
dev->num_products = pdata->num_products;
|
||||
@ -593,8 +604,26 @@ static int __init android_probe(struct platform_device *pdev)
|
||||
return usb_composite_register(&android_usb_driver);
|
||||
}
|
||||
|
||||
static int andr_runtime_suspend(struct device *dev)
|
||||
{
|
||||
dev_dbg(dev, "pm_runtime: suspending...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int andr_runtime_resume(struct device *dev)
|
||||
{
|
||||
dev_dbg(dev, "pm_runtime: resuming...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops andr_dev_pm_ops = {
|
||||
.runtime_suspend = andr_runtime_suspend,
|
||||
.runtime_resume = andr_runtime_resume,
|
||||
};
|
||||
static struct platform_driver android_platform_driver = {
|
||||
.driver = { .name = "android_usb", },
|
||||
.driver = {
|
||||
.name = "android_usb",
|
||||
.pm = &andr_dev_pm_ops},
|
||||
.probe = android_probe,
|
||||
};
|
||||
|
||||
@ -612,6 +641,8 @@ 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);
|
||||
|
@ -31,13 +31,11 @@
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
#include <linux/usb/android_composite.h>
|
||||
#include <mach/board.h>
|
||||
|
||||
#define BULK_BUFFER_SIZE 4096
|
||||
|
||||
/* number of tx requests to allocate */
|
||||
#define TX_REQ_MAX 4
|
||||
#define RX_REQ_MAX 32
|
||||
|
||||
static const char shortname[] = "android_adb";
|
||||
|
||||
@ -57,18 +55,11 @@ struct adb_dev {
|
||||
atomic_t open_excl;
|
||||
|
||||
struct list_head tx_idle;
|
||||
struct list_head rx_idle;
|
||||
struct list_head rx_done;
|
||||
|
||||
wait_queue_head_t read_wq;
|
||||
wait_queue_head_t write_wq;
|
||||
|
||||
/* the request we're currently reading from */
|
||||
struct usb_request *read_req;
|
||||
unsigned char *read_buf;
|
||||
unsigned read_count;
|
||||
|
||||
int maxsize;
|
||||
struct usb_request *rx_req;
|
||||
int rx_done;
|
||||
};
|
||||
|
||||
static struct usb_interface_descriptor adb_interface_desc = {
|
||||
@ -125,22 +116,6 @@ static struct usb_descriptor_header *hs_adb_descs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* string descriptors: */
|
||||
|
||||
static struct usb_string adb_string_defs[] = {
|
||||
[0].s = "ADB",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings adb_string_table = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = adb_string_defs,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *adb_strings[] = {
|
||||
&adb_string_table,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* temporary variable used between adb_open() and adb_gadget_bind() */
|
||||
static struct adb_dev *_adb_dev;
|
||||
@ -179,12 +154,16 @@ static void adb_request_free(struct usb_request *req, struct usb_ep *ep)
|
||||
|
||||
static inline int _lock(atomic_t *excl)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
preempt_disable();
|
||||
if (atomic_inc_return(excl) == 1) {
|
||||
return 0;
|
||||
} else {
|
||||
ret = 0;
|
||||
} else
|
||||
atomic_dec(excl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void _unlock(atomic_t *excl)
|
||||
@ -236,11 +215,9 @@ static void adb_complete_out(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct adb_dev *dev = _adb_dev;
|
||||
|
||||
if (req->status != 0) {
|
||||
dev->rx_done = 1;
|
||||
if (req->status != 0)
|
||||
dev->error = 1;
|
||||
req_put(dev, &dev->rx_idle, req);
|
||||
} else
|
||||
req_put(dev, &dev->rx_done, req);
|
||||
|
||||
wake_up(&dev->read_wq);
|
||||
}
|
||||
@ -275,13 +252,11 @@ static int __init create_bulk_endpoints(struct adb_dev *dev,
|
||||
dev->ep_out = ep;
|
||||
|
||||
/* now allocate requests for our endpoints */
|
||||
for (i = 0; i < RX_REQ_MAX; i++) {
|
||||
req = adb_request_new(dev->ep_out, 512);
|
||||
if (!req)
|
||||
goto fail;
|
||||
req->complete = adb_complete_out;
|
||||
req_put(dev, &dev->rx_idle, req);
|
||||
}
|
||||
req = adb_request_new(dev->ep_out, BULK_BUFFER_SIZE);
|
||||
if (!req)
|
||||
goto fail;
|
||||
req->complete = adb_complete_out;
|
||||
dev->rx_req = req;
|
||||
|
||||
for (i = 0; i < TX_REQ_MAX; i++) {
|
||||
req = adb_request_new(dev->ep_in, BULK_BUFFER_SIZE);
|
||||
@ -329,71 +304,41 @@ static ssize_t adb_read(struct file *fp, char __user *buf,
|
||||
r = -EIO;
|
||||
goto done;
|
||||
}
|
||||
while (count > 0) {
|
||||
if (dev->error) {
|
||||
r = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if we have idle read requests, get them queued */
|
||||
while ((req = req_get(dev, &dev->rx_idle))) {
|
||||
requeue_req:
|
||||
req->length = dev->maxsize?dev->maxsize:512;
|
||||
ret = usb_ep_queue(dev->ep_out, req, GFP_ATOMIC);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "adb_read: failed to queue req (%d)\n", ret);
|
||||
r = -EIO;
|
||||
dev->error = 1;
|
||||
req_put(dev, &dev->rx_idle, req);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we have data pending, give it to userspace */
|
||||
if (dev->read_count > 0) {
|
||||
xfer = (dev->read_count < count) ? dev->read_count : count;
|
||||
|
||||
if (copy_to_user(buf, dev->read_buf, xfer)) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
dev->read_buf += xfer;
|
||||
dev->read_count -= xfer;
|
||||
buf += xfer;
|
||||
count -= xfer;
|
||||
|
||||
/* if we've emptied the buffer, release the request */
|
||||
if (dev->read_count == 0) {
|
||||
req_put(dev, &dev->rx_idle, dev->read_req);
|
||||
dev->read_req = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* wait for a request to complete */
|
||||
req = 0;
|
||||
ret = wait_event_interruptible(dev->read_wq,
|
||||
((req = req_get(dev, &dev->rx_done)) || dev->error));
|
||||
|
||||
if (req != 0) {
|
||||
/* if we got a 0-len one we need to put it back into
|
||||
** service. if we made it the current read req we'd
|
||||
** be stuck forever
|
||||
*/
|
||||
if (req->actual == 0)
|
||||
goto requeue_req;
|
||||
|
||||
dev->read_req = req;
|
||||
dev->read_count = req->actual;
|
||||
dev->read_buf = req->buf;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
r = ret;
|
||||
break;
|
||||
}
|
||||
/* queue a request */
|
||||
req = dev->rx_req;
|
||||
req->length = count;
|
||||
dev->rx_done = 0;
|
||||
ret = usb_ep_queue(dev->ep_out, req, GFP_ATOMIC);
|
||||
if (ret < 0) {
|
||||
DBG(cdev, "adb_read: failed to queue req %p (%d)\n", req, ret);
|
||||
r = -EIO;
|
||||
dev->error = 1;
|
||||
goto done;
|
||||
} else {
|
||||
DBG(cdev, "rx %p queue\n", req);
|
||||
}
|
||||
|
||||
/* wait for a request to complete */
|
||||
ret = wait_event_interruptible(dev->read_wq, dev->rx_done);
|
||||
if (ret < 0) {
|
||||
dev->error = 1;
|
||||
r = ret;
|
||||
goto done;
|
||||
}
|
||||
if (!dev->error) {
|
||||
/* If we got a 0-len packet, throw it back and try again. */
|
||||
if (req->actual == 0)
|
||||
goto requeue_req;
|
||||
|
||||
DBG(cdev, "rx %p %d\n", req, req->actual);
|
||||
xfer = (req->actual < count) ? req->actual : count;
|
||||
if (copy_to_user(buf, req->buf, xfer))
|
||||
r = -EFAULT;
|
||||
} else
|
||||
r = -EIO;
|
||||
|
||||
done:
|
||||
_unlock(&dev->read_excl);
|
||||
DBG(cdev, "adb_read returning %d\n", r);
|
||||
@ -468,9 +413,25 @@ static ssize_t adb_write(struct file *fp, const char __user *buf,
|
||||
|
||||
static int adb_open(struct inode *ip, struct file *fp)
|
||||
{
|
||||
printk(KERN_INFO "adb_open\n");
|
||||
if (_lock(&_adb_dev->open_excl))
|
||||
static unsigned long last_print;
|
||||
static unsigned long count = 0;
|
||||
|
||||
if (++count == 1)
|
||||
last_print = jiffies;
|
||||
else {
|
||||
if (!time_before(jiffies, last_print + HZ/2))
|
||||
count = 0;
|
||||
last_print = jiffies;
|
||||
}
|
||||
|
||||
if (_lock(&_adb_dev->open_excl)) {
|
||||
cpu_relax();
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (count < 5)
|
||||
printk(KERN_INFO "adb_open(%s)\n", current->comm);
|
||||
|
||||
|
||||
fp->private_data = _adb_dev;
|
||||
|
||||
@ -482,7 +443,19 @@ static int adb_open(struct inode *ip, struct file *fp)
|
||||
|
||||
static int adb_release(struct inode *ip, struct file *fp)
|
||||
{
|
||||
printk(KERN_INFO "adb_release\n");
|
||||
static unsigned long last_print;
|
||||
static unsigned long count = 0;
|
||||
|
||||
if (++count == 1)
|
||||
last_print = jiffies;
|
||||
else {
|
||||
if (!time_before(jiffies, last_print + HZ/2))
|
||||
count = 0;
|
||||
last_print = jiffies;
|
||||
}
|
||||
|
||||
if (count < 5)
|
||||
printk(KERN_INFO "adb_release\n");
|
||||
_unlock(&_adb_dev->open_excl);
|
||||
return 0;
|
||||
}
|
||||
@ -580,10 +553,7 @@ adb_function_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
|
||||
spin_lock_irq(&dev->lock);
|
||||
|
||||
while ((req = req_get(dev, &dev->rx_done)))
|
||||
adb_request_free(req, dev->ep_out);
|
||||
while ((req = req_get(dev, &dev->rx_idle)))
|
||||
adb_request_free(req, dev->ep_out);
|
||||
adb_request_free(dev->rx_req, dev->ep_out);
|
||||
while ((req = req_get(dev, &dev->tx_idle)))
|
||||
adb_request_free(req, dev->ep_in);
|
||||
|
||||
@ -603,7 +573,6 @@ static int adb_function_set_alt(struct usb_function *f,
|
||||
struct adb_dev *dev = func_to_dev(f);
|
||||
struct usb_composite_dev *cdev = f->config->cdev;
|
||||
int ret;
|
||||
struct usb_request *req;
|
||||
|
||||
DBG(cdev, "adb_function_set_alt intf: %d alt: %d\n", intf, alt);
|
||||
ret = usb_ep_enable(dev->ep_in,
|
||||
@ -620,17 +589,7 @@ static int adb_function_set_alt(struct usb_function *f,
|
||||
usb_ep_disable(dev->ep_in);
|
||||
return ret;
|
||||
}
|
||||
if (cdev->gadget->speed == USB_SPEED_FULL)
|
||||
dev->maxsize = 64;
|
||||
else
|
||||
dev->maxsize = 512;
|
||||
printk(KERN_INFO "%s: maxsize = %d\n", __func__, dev->maxsize);
|
||||
|
||||
/* retire any completed rx requests from previous session */
|
||||
while ((req = req_get(dev, &dev->rx_done)))
|
||||
req_put(dev, &dev->rx_idle, req);
|
||||
|
||||
dev->online = !dev->function.hidden;
|
||||
dev->online = 1;
|
||||
|
||||
/* readers may be blocked waiting for us to go online */
|
||||
wake_up(&dev->read_wq);
|
||||
@ -645,7 +604,6 @@ static void adb_function_disable(struct usb_function *f)
|
||||
DBG(cdev, "adb_function_disable\n");
|
||||
dev->online = 0;
|
||||
dev->error = 1;
|
||||
dev->maxsize = 0;
|
||||
usb_ep_disable(dev->ep_in);
|
||||
usb_ep_disable(dev->ep_out);
|
||||
|
||||
@ -676,27 +634,18 @@ static int adb_bind_config(struct usb_configuration *c)
|
||||
atomic_set(&dev->write_excl, 0);
|
||||
|
||||
INIT_LIST_HEAD(&dev->tx_idle);
|
||||
INIT_LIST_HEAD(&dev->rx_idle);
|
||||
INIT_LIST_HEAD(&dev->rx_done);
|
||||
|
||||
ret = usb_string_id(c->cdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
adb_string_defs[0].id = ret;
|
||||
adb_interface_desc.iInterface = ret;
|
||||
dev->cdev = c->cdev;
|
||||
dev->function.name = "adb";
|
||||
dev->function.strings = adb_strings;
|
||||
dev->function.descriptors = fs_adb_descs;
|
||||
dev->function.hs_descriptors = hs_adb_descs;
|
||||
dev->function.bind = adb_function_bind;
|
||||
dev->function.unbind = adb_function_unbind;
|
||||
dev->function.set_alt = adb_function_set_alt;
|
||||
dev->function.disable = adb_function_disable;
|
||||
dev->maxsize = 512;
|
||||
|
||||
if (board_mfg_mode() != 2)
|
||||
dev->function.hidden = 1;
|
||||
/* start disabled */
|
||||
// dev->function.disabled = 1;
|
||||
|
||||
/* _adb_dev must be set before calling usb_gadget_register_driver */
|
||||
_adb_dev = dev;
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Copyright (C) 2003-2005,2008 David Brownell
|
||||
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
|
||||
* Copyright (C) 2008 Nokia Corporation
|
||||
* Copyright (C) 2009 Samsung Electronics
|
||||
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -22,6 +24,7 @@
|
||||
|
||||
/* #define VERBOSE_DEBUG */
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/etherdevice.h>
|
||||
@ -84,6 +87,8 @@ struct f_rndis {
|
||||
struct gether port;
|
||||
u8 ctrl_id, data_id;
|
||||
u8 ethaddr[ETH_ALEN];
|
||||
u32 vendorID;
|
||||
const char *manufacturer;
|
||||
int config;
|
||||
|
||||
struct rndis_ep_descs fs;
|
||||
@ -95,6 +100,8 @@ struct f_rndis {
|
||||
atomic_t notify_count;
|
||||
};
|
||||
|
||||
static char manufacturer [10] = "HTC";
|
||||
static u32 vendorID = 0x0bb4;
|
||||
static inline struct f_rndis *func_to_rndis(struct usb_function *f)
|
||||
{
|
||||
return container_of(f, struct f_rndis, port.func);
|
||||
@ -412,8 +419,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
||||
*/
|
||||
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
|
||||
| USB_CDC_SEND_ENCAPSULATED_COMMAND:
|
||||
if (w_length > req->length || w_value
|
||||
|| w_index != rndis->ctrl_id)
|
||||
if (w_value || w_index != rndis->ctrl_id)
|
||||
goto invalid;
|
||||
/* read the request; process it later */
|
||||
value = w_length;
|
||||
@ -820,6 +826,8 @@ int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
|
||||
goto fail;
|
||||
|
||||
memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
|
||||
rndis->vendorID = vendorID;
|
||||
rndis->manufacturer = manufacturer;
|
||||
|
||||
/* RNDIS activates when the host changes this filter */
|
||||
rndis->port.cdc_filter = 0;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -291,9 +291,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
|
||||
/* mandatory */
|
||||
case OID_GEN_VENDOR_DESCRIPTION:
|
||||
pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
|
||||
length = strlen (rndis_per_dev_params [configNr].vendorDescr);
|
||||
memcpy (outbuf,
|
||||
rndis_per_dev_params [configNr].vendorDescr, length);
|
||||
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;
|
||||
}
|
||||
retval = 0;
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user