summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2015-01-12 13:29:16 +0800
committerAndy Green <andy.green@linaro.org>2015-02-04 20:43:59 +0800
commitda5a8ca8813d17511acc0905603879a3d7f15724 (patch)
treecdf2097a838a2c67a815701c39b0df0ebccaf6a5
parentc31811bb0c79066ac3b7beed1a79703af46581d3 (diff)
bluetooth smdtty ch3 hacks
This teaches smdtty that ch3 (HCI) and ch2 (ACL) are related, and deals with faking up and removing the channel usage type byte expected by UART HCI protocol. This is enough that you can just point bluez to /dev/smd3 with no patches needed on bluez. Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r--arch/arm/configs/msm8916-qrd_defconfig18
-rw-r--r--drivers/tty/serial/msm_smd_tty.c89
2 files changed, 90 insertions, 17 deletions
diff --git a/arch/arm/configs/msm8916-qrd_defconfig b/arch/arm/configs/msm8916-qrd_defconfig
index 4d06b3542163..a5b5bdc8d383 100644
--- a/arch/arm/configs/msm8916-qrd_defconfig
+++ b/arch/arm/configs/msm8916-qrd_defconfig
@@ -68,6 +68,16 @@ CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
CONFIG_CFG80211=y
CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_INTERNAL_REGDB=y
@@ -96,15 +106,18 @@ CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_USB_NET_DRIVERS is not set
-CONFIG_WCNSS_CORE=m
-CONFIG_WCNSS_CORE_PRONTO=m
CONFIG_ATH_CARDS=y
CONFIG_ATH_DEBUG=y
CONFIG_WCN36XX=m
CONFIG_WCN36XX_DEBUGFS=y
# CONFIG_RTL_CARDS is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_SMD=y
CONFIG_HW_RANDOM=y
CONFIG_MSM_SMD_PKT=y
CONFIG_SPMI=y
@@ -125,6 +138,7 @@ CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_HIDRAW=y
# CONFIG_USB_HID is not set
CONFIG_USB=y
CONFIG_USB_OTG=y
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
index 740e34c5024b..98b7dbe68f66 100644
--- a/drivers/tty/serial/msm_smd_tty.c
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -110,6 +110,8 @@ struct smd_tty_info {
char ch_name[SMD_MAX_CH_NAME_LEN];
char dev_name[SMD_MAX_CH_NAME_LEN];
+ bool swallow_first_tx_byte;
+
struct mutex open_lock_lha1;
unsigned int open_wait;
@@ -265,9 +267,16 @@ static void smd_tty_read(unsigned long param)
unsigned char *ptr;
int avail;
struct smd_tty_info *info = (struct smd_tty_info *)param;
- struct tty_struct *tty = tty_port_tty_get(&info->port);
+ struct smd_tty_info *info_smd = info;
+
+ struct tty_struct *tty;
unsigned long flags;
+ if (info == &smd_tty[2])
+ info = &smd_tty[3];
+
+ tty = tty_port_tty_get(&info->port);
+
if (!tty)
return;
@@ -282,12 +291,14 @@ static void smd_tty_read(unsigned long param)
if (test_bit(TTY_THROTTLED, &tty->flags))
break;
spin_lock_irqsave(&info->ra_lock_lha3, flags);
- avail = smd_read_avail(info->ch);
+ avail = smd_read_avail(info_smd->ch);
if (avail == 0) {
__pm_relax(&info->ra_wakeup_source);
spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
break;
}
+ if (info->swallow_first_tx_byte)
+ avail++;
spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
if (avail > MAX_TTY_BUF_SIZE)
@@ -300,16 +311,30 @@ static void smd_tty_read(unsigned long param)
tty_kref_put(tty);
return;
}
-
- if (smd_read(info->ch, ptr, avail) != avail) {
- /* shouldn't be possible since we're in interrupt
- ** context here and nobody else could 'steal' our
- ** characters.
- */
- SMD_TTY_ERR(
- "%s - Possible smd_tty_buffer mismatch for %s",
- __func__, info->ch_name);
- }
+ if (info->swallow_first_tx_byte) {
+ if (info == info_smd)
+ *ptr = 4; /* HCI EVENT */
+ else
+ *ptr = 2; /* ACL */
+ if (smd_read(info_smd->ch, ptr + 1, avail - 1) != avail - 1) {
+ /* shouldn't be possible since we're in interrupt
+ ** context here and nobody else could 'steal' our
+ ** characters.
+ */
+ SMD_TTY_ERR(
+ "%s - Possible smd_tty_buffer mismatch for %s",
+ __func__, info->ch_name);
+ }
+ } else
+ if (smd_read(info_smd->ch, ptr, avail) != avail) {
+ /* shouldn't be possible since we're in interrupt
+ ** context here and nobody else could 'steal' our
+ ** characters.
+ */
+ SMD_TTY_ERR(
+ "%s - Possible smd_tty_buffer mismatch for %s",
+ __func__, info->ch_name);
+ }
/*
* Keep system awake long enough to allow the TTY
@@ -635,6 +660,22 @@ static int smd_tty_port_activate(struct tty_port *tport,
goto release_wl_tl;
}
+ if (info->swallow_first_tx_byte) {
+ tasklet_init(&smd_tty[2].tty_tsklt, smd_tty_read, (unsigned long)&smd_tty[2]);
+
+ res = smd_named_open_on_edge("APPS_RIVA_BT_ACL",
+ SMD_APPS_WCNSS, &smd_tty[2].ch, &smd_tty[2],
+ smd_tty_notify);
+
+ if (res < 0) {
+ SMD_TTY_INFO("%s: %s open failed %d\n",
+ __func__, info->ch_name, res);
+ goto release_wl_tl;
+ }
+
+
+ }
+
res = wait_event_interruptible_timeout(info->ch_opened_wait_queue,
info->is_open, (2 * HZ));
if (res == 0)
@@ -647,6 +688,8 @@ static int smd_tty_port_activate(struct tty_port *tport,
SMD_TTY_INFO("%s with PID %u opened port %s",
current->comm, current->pid, info->ch_name);
smd_disable_read_intr(info->ch);
+ smd_disable_read_intr(smd_tty[2].ch);
+
mutex_unlock(&info->open_lock_lha1);
return 0;
@@ -701,6 +744,10 @@ static void smd_tty_port_shutdown(struct tty_port *tport)
smd_close(info->ch);
info->ch = NULL;
+
+ if (info->swallow_first_tx_byte)
+ smd_close(smd_tty[2].ch);
+
subsystem_put(info->pil);
smd_tty_remove_driver(info);
@@ -727,6 +774,10 @@ static int smd_tty_write(struct tty_struct *tty, const unsigned char *buf,
{
struct smd_tty_info *info = tty->driver_data;
int avail;
+ smd_channel_t *ch = info->ch;
+
+ if (info->swallow_first_tx_byte && *buf != 1)
+ ch = smd_tty[2].ch;
/* if we're writing to a packet channel we will
** never be able to write more data than there
@@ -735,12 +786,12 @@ static int smd_tty_write(struct tty_struct *tty, const unsigned char *buf,
if (is_in_reset(info))
return -ENETRESET;
- avail = smd_write_avail(info->ch);
+ avail = smd_write_avail(ch);
/* if no space, we'll have to setup a notification later to wake up the
* tty framework when space becomes avaliable
*/
if (!avail) {
- smd_enable_read_intr(info->ch);
+ smd_enable_read_intr(ch);
return 0;
}
if (len > avail)
@@ -748,7 +799,13 @@ static int smd_tty_write(struct tty_struct *tty, const unsigned char *buf,
SMD_TTY_INFO("[WRITE]: PID %u -> port %s %x bytes",
current->pid, info->ch_name, len);
- return smd_write(info->ch, buf, len);
+ if (info->swallow_first_tx_byte) {
+ if (len < 2)
+ return 0;
+ return smd_write(ch, buf + 1, len - 1) + 1;
+ }
+
+ return smd_write(ch, buf, len);
}
static int smd_tty_write_room(struct tty_struct *tty)
@@ -913,6 +970,7 @@ static void smd_tty_device_init(int idx)
port = &smd_tty[idx].port;
tty_port_init(port);
port->ops = &smd_tty_port_ops;
+ smd_tty[idx].swallow_first_tx_byte = idx == 3;
smd_tty[idx].device_ptr = tty_port_register_device(port, smd_tty_driver,
idx, NULL);
init_completion(&smd_tty[idx].ch_allocated);
@@ -946,6 +1004,7 @@ static int smd_tty_core_init(void)
for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
idx = smd_configs[n].tty_dev_index;
smd_tty[idx].edge = smd_configs[n].edge;
+ smd_tty[idx].swallow_first_tx_byte = idx == 3;
strlcpy(smd_tty[idx].ch_name, smd_configs[n].port_name,
SMD_MAX_CH_NAME_LEN);