Exemplo n.º 1
0
static int smd_tty_write(struct tty_struct *tty, const unsigned char *buf, int len)
{
	struct smd_tty_info *info = tty->driver_data;
	int avail;

	/* if we're writing to a packet channel we will
	** never be able to write more data than there
	** is currently space for
	*/
	if (is_in_reset(info))
		return -ENETRESET;

	avail = smd_write_avail(info->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);
		return 0;
	}
	if (len > avail)
		len = avail;

	return smd_write(info->ch, buf, len);
}
Exemplo n.º 2
0
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);
	unsigned long flags;

	if (!tty)
		return;

	for (;;) {
		if (is_in_reset(info)) {
			/* signal TTY clients using TTY_BREAK */
			tty_insert_flip_char(tty, 0x00, TTY_BREAK);
			tty_flip_buffer_push(tty);
			break;
		}

		if (test_bit(TTY_THROTTLED, &tty->flags)) break;
		spin_lock_irqsave(&info->ra_lock, flags);
		avail = smd_read_avail(info->ch);
		if (avail == 0) {
			wake_unlock(&info->ra_wake_lock);
			spin_unlock_irqrestore(&info->ra_lock, flags);
			break;
		}
		spin_unlock_irqrestore(&info->ra_lock, flags);

		if (avail > MAX_TTY_BUF_SIZE)
			avail = MAX_TTY_BUF_SIZE;

		avail = tty_prepare_flip_string(tty, &ptr, avail);
		if (avail <= 0) {
			mod_timer(&info->buf_req_timer,
					jiffies + msecs_to_jiffies(30));
			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);
		}

		wake_lock_timeout(&info->wake_lock, HZ / 2);
		tty_flip_buffer_push(tty);
	}

	/* XXX only when writable and necessary */
	tty_wakeup(tty);
	tty_kref_put(tty);
}
Exemplo n.º 3
0
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 = info->tty;

	if (!tty)
		return;

	for (;;) {
		unsigned int n = info->tty->index;
		if (is_in_reset(info)) {
			if (n == BT_ACL_IDX || n == BT_CMD_IDX)
				pr_err("%s: BT_IDX read in reset %d \n", __func__, n);
			if ((n != BT_ACL_IDX) && (n != BT_CMD_IDX)) {
			/* signal TTY clients using TTY_BREAK */
				tty_insert_flip_char(tty, 0x00, TTY_BREAK);
				tty_flip_buffer_push(tty);
				break;
			}
		}

		if (test_bit(TTY_THROTTLED, &tty->flags)) break;
		avail = smd_read_avail(info->ch);
		if (avail == 0)
			break;

		if (avail > MAX_TTY_BUF_SIZE)
			avail = MAX_TTY_BUF_SIZE;

		avail = tty_prepare_flip_string(tty, &ptr, avail);
		if (avail <= 0) {
			mod_timer(&info->buf_req_timer,
					jiffies + msecs_to_jiffies(30));
			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.
			*/
			printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!");
		}

#ifdef CONFIG_HAS_WAKELOCK
		pr_debug("%s: lock wakelock %s\n", __func__, info->wake_lock.name);
#endif
		wake_lock_timeout(&info->wake_lock, HZ / 2);
		tty_flip_buffer_push(tty);
	}

	/* XXX only when writable and necessary */
	tty_wakeup(tty);
}
Exemplo n.º 4
0
static int hsic_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
{
    struct hsic_tty_info *info = tty->driver_data;
    unsigned n = tty->index;
    struct tdata_port *port = info->dport;
    unsigned port_num;

    pr_debug("%s:#%d set(%04X), clear(%04X)\n", __func__, n, set, clear);
    if (is_in_reset(info))
    {
        pr_debug("%s: is in reset\n", __func__);
        return -ENETRESET;
    }

    if (info->tty->index != n)
    {
        pr_debug("%s: tty(%d) and info->tty(%d) dismatch, ignore it.\n",
                __func__, n, info->tty->index);
        return 0;
    }

    port_num = info->client_port_num;

    /* set */
    info->port_handshake_bits |= 
        ((set & TIOCM_DTR) ? ACM_CTRL_DTR : 0) | ((set & TIOCM_RTS) ? ACM_CTRL_RTS : 0);
    /* clear */
    info->port_handshake_bits &= 
        ~(((clear & TIOCM_DTR) ? ACM_CTRL_DTR : 0) | ((clear & TIOCM_RTS) ? ACM_CTRL_RTS : 0));

    info->notify_modem(info, port_num, info->port_handshake_bits);

    if ((info->port_handshake_bits & ACM_CTRL_DTR) &&
            !(info->port_handshake_bits & ACM_CTRL_RTS))
    {
        info->port_handshake_bits |= ACM_CTRL_RTS;
        info->notify_modem(info, port_num, info->port_handshake_bits);
    }

    if (!(info->port_handshake_bits & ACM_CTRL_DTR) &&
            (info->port_handshake_bits & ACM_CTRL_RTS))
    {
        info->port_handshake_bits &= ~ACM_CTRL_RTS;
        info->notify_modem(info, port_num, info->port_handshake_bits);
    }

    if (info->port_handshake_bits & (ACM_CTRL_DTR | ACM_CTRL_RTS))
    {
        pr_debug("%s: ACM_CTRL_DTR and ACM_CTRL_RTS is set. start write_tomdm\n", __func__);
        spin_lock(&port->rx_lock);
        queue_work(port->wq, &port->write_tomdm_w);
        spin_unlock(&port->rx_lock);
    }

    return 0;
}
Exemplo n.º 5
0
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 = info->tty;

    if (!tty)
        return;

    for (;;) {
        if (is_in_reset(info)) {
            /* signal TTY clients using TTY_BREAK */
            tty_insert_flip_char(tty, 0x00, TTY_BREAK);
            tty_flip_buffer_push(tty);
            break;
        }

        if (test_bit(TTY_THROTTLED, &tty->flags))
            break;
        avail = smd_read_avail(info->ch);
        if (avail == 0)
            break;

        if (avail > MAX_TTY_BUF_SIZE)
            avail = MAX_TTY_BUF_SIZE;

        avail = tty_prepare_flip_string(tty, &ptr, avail);
        if (avail <= 0) {
            if (!timer_pending(&info->buf_req_timer)) {
                init_timer(&info->buf_req_timer);
                info->buf_req_timer.expires = jiffies +
                                              ((30 * HZ)/1000);
                info->buf_req_timer.function = buf_req_retry;
                info->buf_req_timer.data = param;
                add_timer(&info->buf_req_timer);
            }
            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.
            */
            printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!");
        }

        wake_lock_timeout(&info->wake_lock, HZ / 2);
        tty_flip_buffer_push(tty);
    }

    /* XXX only when writable and necessary */
    tty_wakeup(tty);
}
Exemplo n.º 6
0
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 = info->tty;

	if (!tty)
		return;

	for (;;) {
		if (is_in_reset(info)) {
			
			tty_insert_flip_char(tty, 0x00, TTY_BREAK);
			tty_flip_buffer_push(tty);
			break;
		}

		if (test_bit(TTY_THROTTLED, &tty->flags)) break;
		avail = smd_read_avail(info->ch);
		if (avail == 0)
			break;

		if (avail > MAX_TTY_BUF_SIZE)
			avail = MAX_TTY_BUF_SIZE;

		avail = tty_prepare_flip_string(tty, &ptr, avail);
		if (avail <= 0) {
			mod_timer(&info->buf_req_timer,
					jiffies + msecs_to_jiffies(30));
			return;
		}

		if (smd_read(info->ch, ptr, avail) != avail) {
			printk(KERN_ERR "OOPS - smd_tty_buffer mismatch?!");
		
		} else {
			if (get_radio_flag() & 0x0008) {
				int i = 0;
				printk("[RIL]");
				for (i = 0; i< avail; i++)
					printk("%c", *(ptr+i));
			}
		
		}

		wake_lock_timeout(&info->wake_lock, HZ / 2);
		tty_flip_buffer_push(tty);
	}

	
	tty_wakeup(tty);
}
Exemplo n.º 7
0
static int smd_tty_write(struct tty_struct *tty, const unsigned char *buf, int len)
{
	struct smd_tty_info *info = tty->driver_data;
	int avail;

	if (is_in_reset(info))
		return -ENETRESET;

	avail = smd_write_avail(info->ch);
	if (!avail) {
		smd_enable_read_intr(info->ch);
		return 0;
	}
	if (len > avail)
		len = avail;

	return smd_write(info->ch, buf, len);
}
Exemplo n.º 8
0
static int hsic_tty_write(struct tty_struct *tty, const unsigned char *buf, int len)
{
    struct hsic_tty_info *info = tty->driver_data;
    unsigned n = tty->index;
    struct tdata_port *port = info->dport;
    struct sk_buff		*skb;

    pr_debug("%s:#%d\n", __func__, n);

    /* if we're writing to a packet channel we will
     ** never be able to write more data than there
     ** is currently space for
     */
    if (is_in_reset(info))
    {
        pr_debug("%s: is in reset\n", __func__);
        return -ENETRESET;
    }

    if (info->tty->index != n)
    {
        pr_debug("%s: tty(%d) and info->tty(%d) dismatch, ignore it.\n",
                __func__, n, info->tty->index);
        return len;
    }

    skb = alloc_skb(len, GFP_ATOMIC);
	if(!skb)
	{
		pr_debug("%s: len alloc failed\n", __func__);
		return -ENOMEM;
	}
	skb->data = (unsigned char *)buf;
    skb->len = len;

    spin_lock(&port->rx_lock);
    __skb_queue_tail(&port->rx_skb_q, skb);
    if (info->port_handshake_bits & ACM_CTRL_DTR)
        queue_work(port->wq, &port->write_tomdm_w);
    spin_unlock(&port->rx_lock);

    return len;
}
Exemplo n.º 9
0
static void smd_tty_notify(void *priv, unsigned event)
{
	struct smd_tty_info *info = priv;
	unsigned long flags;
	unsigned char *ptr;

	switch (event) {
	case SMD_EVENT_DATA:
		spin_lock_irqsave(&info->reset_lock, flags);
		if (!info->is_open) {
			spin_unlock_irqrestore(&info->reset_lock, flags);
			break;
		}
		spin_unlock_irqrestore(&info->reset_lock, flags);
		/* There may be clients (tty framework) that are blocked
		 * waiting for space to write data, so if a possible read
		 * interrupt came in wake anyone waiting and disable the
		 * interrupts
		 */
		if (smd_write_avail(info->ch)) {
			smd_disable_read_intr(info->ch);
			if (info->tty) {
				unsigned int n = info->tty->index;
				wake_up_interruptible(&info->tty->write_wait);

				/* use pm_qos for BT performance */
				if (n == BT_ACL_IDX || n == BT_CMD_IDX)
					schedule_work(&pm_qos_set_work);
			}
		}
		tasklet_hi_schedule(&info->tty_tsklt);
		break;

	case SMD_EVENT_OPEN:
		if (is_in_reset(info)) {
			unsigned int n = info->tty->index;
			if (n == BT_CMD_IDX) {
				pr_err("%s:  BT_CMD_IDX Sending hardware error event to stack\n", __func__);
				tty_prepare_flip_string(info->tty, &ptr, 0x03);
				ptr[0] = 0x10;
				ptr[1] = 0x01;
				ptr[2] = 0x0A;
				tty_flip_buffer_push(info->tty);
			}
		}
		spin_lock_irqsave(&info->reset_lock, flags);
		info->in_reset = 0;
		info->in_reset_updated = 1;
		info->is_open = 1;
		wake_up_interruptible(&info->ch_opened_wait_queue);
		spin_unlock_irqrestore(&info->reset_lock, flags);

		break;

	case SMD_EVENT_CLOSE:
		spin_lock_irqsave(&info->reset_lock, flags);
		info->in_reset = 1;
		info->in_reset_updated = 1;
		info->is_open = 0;
		wake_up_interruptible(&info->ch_opened_wait_queue);
		spin_unlock_irqrestore(&info->reset_lock, flags);
		/* schedule task to send TTY_BREAK */
		tasklet_hi_schedule(&info->tty_tsklt);

		if (info->tty->index == LOOPBACK_IDX)
			schedule_delayed_work(&loopback_work,
					msecs_to_jiffies(1000));
		break;
	}
}
Exemplo n.º 10
0
static int smd_tty_write(struct tty_struct *tty, const unsigned char *buf, int len)
{
	struct smd_tty_info *info = tty->driver_data;
	int avail, ret, runfix = 0;
#ifdef CONFIG_MACH_HTCLEO
	static int init = 0;
	// seems to start the modem
	const unsigned char* firstcall ="AT@BRIC=0\r";
	// set functionality to low power mode
	const unsigned char* secondcall="AT+CFUN=0\r";
	// deregister from the network
	const unsigned char* thirdcall ="AT+COPS=2\r";
	unsigned int call_len;
#endif

	/* if we're writing to a packet channel we will
	** never be able to write more data than there
	** is currently space for
	*/
	if (is_in_reset(info))
		return -ENETRESET;

#ifdef CONFIG_MACH_HTCLEO
	if(len>7 && !init && htcleo_is_nand_boot()) {
		pr_info("NAND boot, writing additional init commands to /dev/smd0");

		call_len = strlen(firstcall);
		avail = smd_write_avail(info->ch);
		if (call_len > avail)
			call_len = avail;
		ret = smd_write(info->ch, firstcall, call_len);

		call_len = strlen(secondcall);
		avail = smd_write_avail(info->ch);
		if (call_len > avail)
			call_len = avail;
		ret = smd_write(info->ch, secondcall, call_len);

		call_len = strlen(thirdcall);
		avail = smd_write_avail(info->ch);
		if (call_len > avail)
			call_len = avail;
		ret = smd_write(info->ch, thirdcall, call_len);

		init=1;
	}
#endif

	avail = smd_write_avail(info->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);
		return 0;
	}
	if (len > avail)
		len = avail;

	return smd_write(info->ch, buf, len);
}