mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] drivers: staging: GPS protocol driver for wl128x
@ 2010-05-04 16:25 Pavan Savoy
  2010-05-05 11:11 ` Alan Cox
  0 siblings, 1 reply; 6+ messages in thread
From: Pavan Savoy @ 2010-05-04 16:25 UTC (permalink / raw)
  To: greg, alan; +Cc: linux-kernel

Greg, Alan,

Just to complete the circle on N_TI_WL, find below the GPS driver which makes use of the shared transport line discipline.

This driver provides a TTY line character device to application/middle-ware running on host, as if the device is directly connected over UART to a GPS chip.

Almost all actions that can be done on a /dev/ttySx can be done on this /dev/tigps device.

So with Bluetooth and GPS drivers as the consumers of this N_TI_WL line discipline, how can I tweak the line discipline driver for proper submission [out of staging] ?
(will send out the patch for Kconfig/Makefile once you guys have a look at this..)

>From dc6c64e732bb662471a1f9b95f8f68ab657e30e6 Mon Sep 17 00:00:00 2001
From: Pavan Savoy <pavan_savoy@ti.com>
Date: Mon, 3 May 2010 17:41:23 -0600
Subject: [PATCH] drivers: staging: GPS protocol driver for wl128x

Texas Instrument's wl128x connectivity combo chip
has BT, FM and GPS interfaced to host/apps processor
over a single UART.
This is the driver for the GPS protocol which makes use of
the N_TI_WL TTY line discipline.

Signed-off-by: Pavan Savoy <pavan_savoy@ti.com>
Signed-off-by: Nagarjuna Kristam <x0043706@ti.com>
Signed-off-by: Sunil Pillai <sunil_pillai@ti.com>
---
 drivers/staging/ti-st/gps_drv.c |  732 +++++++++++++++++++++++++++++++++++++++
 drivers/staging/ti-st/gps_drv.h |   91 +++++
 2 files changed, 823 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/ti-st/gps_drv.c
 create mode 100644 drivers/staging/ti-st/gps_drv.h

diff --git a/drivers/staging/ti-st/gps_drv.c b/drivers/staging/ti-st/gps_drv.c
new file mode 100644
index 0000000..cbc0dac
--- /dev/null
+++ b/drivers/staging/ti-st/gps_drv.c
@@ -0,0 +1,732 @@
+/*
+ *   GPS Char Driver for Texas Instrument's Connectivity Chip.
+ *   Copyright (C) 2009 Texas Instruments
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2 as
+ *   published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt)	"(gps): " fmt
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+
+#include <linux/uaccess.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+
+#include "gps_drv.h"
+#include "st.h"
+
+#define DEVICE_NAME     "tigps"
+
+/* Initialization TaskLet for performing GPS Write */
+DECLARE_TASKLET_DISABLED(gpsdrv_tx_tsklet, gpsdrv_tsklet_write, 0);
+
+/* Structure declerations for GPS char Driver Data */
+static struct gpsdrv_data *hgps;
+
+/***********Functions called from ST driver**********************************/
+
+/*  gpsdrv_st_recv Function
+ *  This is Called in from -- ST Core when a data is received
+ *  This is a registered callback with ST core when the gps driver registers
+ *  with ST.
+ *
+ *  Parameters:
+ *  @skb    : SKB buffer pointer which contains the incoming Ch-9 GPS data.
+ *  Returns:
+ *          GPS_SUCCESS - On Success
+ *          else suitable error code
+ */
+long gpsdrv_st_recv(struct sk_buff *skb)
+{
+	struct gpsdrv_event_hdr gpsdrv_hdr = { 0x00, 0x0000 };
+
+#ifdef VERBOSE
+	unsigned int i;
+#endif
+
+	/* SKB is NULL */
+	if (NULL == skb) {
+		pr_err("Input SKB is NULL");
+		return GPS_ERR_FAILURE;
+	}
+
+	/* Sanity Check - To Check if the Rx Pkt is Channel -9 or not */
+	if (0x09 != skb->cb[0]) {
+		pr_err("Input SKB is not a Channel-9 packet");
+		return GPS_ERR_FAILURE;
+	}
+	/* Copy Ch-9 info to local structure */
+	memcpy(&gpsdrv_hdr, skb->data, GPS_CH9_PKT_HDR_SIZE - 1);
+	skb_pull(skb, GPS_CH9_PKT_HDR_SIZE - 1);
+
+	/* check if skb->len and gpsdrv_hdr.plen are equal */
+	if (skb->len != gpsdrv_hdr.plen) {
+		pr_err("Received corrupted packet - Length Mismatch");
+		return -EINVAL;
+	}
+#ifdef VERBOSE
+	printk(KERN_INFO"data start >>\n");
+	for (i = 0; i < skb->len; i++)
+		printk(KERN_INFO" %x ", skb->data[i]);
+	printk(KERN_INFO"\n<< end\n");
+#endif
+	/* Check the Opcode */
+	if ((gpsdrv_hdr.opcode != GPS_CH9_OP_READ) && (gpsdrv_hdr.opcode != \
+						GPS_CH9_OP_COMPLETED_EVT)) {
+		pr_err("Rec corrupt pkt opcode %x", gpsdrv_hdr.opcode);
+		return -EINVAL;
+	}
+
+	/* Strip Channel 9 packet information from SKB only
+	 * if the opcode is GPS_CH9_OP_READ and get AI2 packet
+	 */
+	if (GPS_CH9_OP_READ == gpsdrv_hdr.opcode) {
+		spin_lock(&hgps->lock);
+		skb_queue_tail(&hgps->rx_list, skb);
+		spin_unlock(&hgps->lock);
+		wake_up_interruptible(&hgps->gpsdrv_data_q);
+	} else {
+		/* Copy Ch-9 info to local structure */
+		memcpy(&hgps->tx_count, skb->data, 1);
+		pr_info(" Tx count = %x", hgps->tx_count);
+		/* Check if Tx queue and Tx count not empty */
+		if ((0 != hgps->tx_count) && \
+			(!skb_queue_empty(&hgps->tx_list))) {
+			/* Schedule the Tx-task let */
+			pr_info(" Scheduling tasklet to write");
+			tasklet_schedule(&gpsdrv_tx_tsklet);
+		}
+		/* Free the received command complete SKB */
+		kfree(skb);
+	}
+
+	return GPS_SUCCESS;
+
+}
+
+/*  gpsdrv_st_cb Function
+ *  This is Called in from -- ST Core when the state is pending during
+ *  st_register. This is a registered callback with ST core when the gps
+ *  driver registers with ST.
+ *
+ *  Parameters:
+ *  @data   Status update of GPS registration
+ *  Returns: NULL
+ */
+void gpsdrv_st_cb(char data)
+{
+	pr_info(" Inside %s", __func__);
+	hgps->streg_cbdata = data;	/* ST registration callback  status */
+	complete_all(&hgps->gpsdrv_reg_completed);
+	return;
+}
+
+static struct st_proto_s gpsdrv_proto = {
+	.type = ST_GPS,
+	.recv = gpsdrv_st_recv,
+	.reg_complete_cb = gpsdrv_st_cb,
+};
+
+/** gpsdrv_tsklet_write Function
+ *  This tasklet function will be scheduled when there is a data in Tx queue
+ *  and GPS chip sent an command completion packet with non zero value.
+ *
+ *  Parameters :
+ *  @data  : data passed to tasklet function
+ *  Returns : NULL
+ */
+void gpsdrv_tsklet_write(unsigned long data)
+{
+	struct sk_buff *skb = NULL;
+
+	pr_info(" Inside %s", __func__);
+
+	/* Perform sanity check of verifying the status
+				to perform an st_write */
+	if (((!hgps->st_write) || (0 == hgps->tx_count))
+			|| ((skb_queue_empty(&hgps->tx_list)))) {
+		pr_err("Sanity check Failed exiting %s", __func__);
+		return;
+	}
+	/* hgps->tx_list not empty skb already present
+	 * dequeue the tx-data and perform a st_write
+	 */
+	spin_lock(&hgps->lock);
+	skb = skb_dequeue(&hgps->tx_list);
+	spin_unlock(&hgps->lock);
+	hgps->st_write(skb);
+	hgps->tx_count--;
+
+	/* Check if Tx queue and Tx count not empty */
+	if ((0 != hgps->tx_count) && (!skb_queue_empty(&hgps->tx_list))) {
+		/* Schedule the Tx-task let */
+		tasklet_schedule(&gpsdrv_tx_tsklet);
+	}
+
+	return;
+}
+
+/*********Functions Called from GPS host***************************************/
+
+/** gpsdrv_open Function
+ *  This function will perform an register on ST driver.
+ *
+ *  Parameters :
+ *  @file  : File pointer for GPS char driver
+ *  @inod  :
+ *  Returns  GPS_SUCCESS -  on success
+ *           else suitable error code
+ */
+int gpsdrv_open(struct inode *inod, struct file *file)
+{
+	int ret = 0;
+	unsigned long timeout = GPSDRV_REG_TIMEOUT;
+
+	pr_info(" Inside %s", __func__);
+	/* Check if GPS is already registered with ST */
+	if (test_and_set_bit(GPS_ST_REGISTERED, &hgps->state)) {
+		pr_err("GPS Registered/Registration in progress with ST \
+							,open called again?");
+
+		return GPS_ERR_ALREADY;
+	}
+
+	/* Initialize  gpsdrv_reg_completed so as to wait for completion
+	* on the same
+	* if st_register returns with a PENDING status
+	*/
+	INIT_COMPLETION(hgps->gpsdrv_reg_completed);
+
+	/* Resgister GPS with ST */
+	ret = st_register(&gpsdrv_proto);
+
+	pr_info(" st_register returned %d", ret);
+
+	/* If GPS Registration returned with error, then clear GPS_ST_REGISTERED
+	 * for future open calls and return the appropriate error code
+	 */
+	if (ret < 0 && ret != ST_ERR_PENDING) {
+		pr_err(" st_register failed");
+		clear_bit(GPS_ST_REGISTERED, &hgps->state);
+		if (ret == ST_ERR_ALREADY)
+			return GPS_ERR_ALREADY;
+		return GPS_ERR_FAILURE;
+	}
+
+	/* if returned status is pending, wait for the completion */
+	if (ret == ST_ERR_PENDING) {
+		pr_info(" GPS Register waiting for completion ");
+		timeout = wait_for_completion_timeout \
+		    (&hgps->gpsdrv_reg_completed, msecs_to_jiffies(timeout));
+		/* Check for timed out condition */
+		if (0 == timeout) {
+			pr_err("st_register failed-GPS Device \
+						Registration timed out");
+			clear_bit(GPS_ST_REGISTERED, &hgps->state);
+			return GPS_ERR_TIMEOUT;
+		} else if (0 > hgps->streg_cbdata) {
+			pr_err("GPS Device Registration Failed-ST \
+								Reg CB called"
+				   "with ivalid value %d", hgps->streg_cbdata);
+			clear_bit(GPS_ST_REGISTERED, &hgps->state);
+			return -EAGAIN;
+		}
+	}
+	pr_info(" gps registration complete ");
+
+	/* Assign the write callback pointer */
+	hgps->st_write = gpsdrv_proto.write;
+	hgps->tx_count = 1;
+	tasklet_enable(&gpsdrv_tx_tsklet);
+	set_bit(GPS_ST_RUNNING, &hgps->state);
+
+	return GPS_SUCCESS;
+}
+
+/** gpsdrv_release Function
+ *  This function will un-registers from the ST driver.
+ *
+ *  Parameters :
+ *  @file  : File pointer for GPS char driver
+ *  @inod  :
+ *  Returns  GPS_SUCCESS -  on success
+ *           else suitable error code
+ */
+int gpsdrv_release(struct inode *inod, struct file *file)
+{
+	pr_info(" Inside %s", __func__);
+
+	/* Disabling task-let 1st & then un-reg to avoid
+	 * tasklet getting scheduled
+	 */
+	tasklet_disable(&gpsdrv_tx_tsklet);
+	/* Cleat registered bit if already registered */
+	if (test_and_clear_bit(GPS_ST_REGISTERED, &hgps->state)) {
+		if (st_unregister(gpsdrv_proto.type) < 0) {
+			pr_err(" st_unregister failed");
+			/* Re-Enable the task-let if un-register fails */
+			tasklet_enable(&gpsdrv_tx_tsklet);
+			return GPS_ERR_FAILURE;
+		}
+	}
+
+	/* Reset Tx count value and st_write function pointer */
+	hgps->tx_count = 0;
+	hgps->st_write = NULL;
+	clear_bit(GPS_ST_RUNNING, &hgps->state);
+	pr_info(" st_unregister success");
+
+	return GPS_SUCCESS;
+}
+
+/** gpsdrv_read Function
+ *  This function will wait till the data received from the ST driver
+ *  and then strips the GPS-Channel-9 header from the
+ *  incoming AI2 packet and then send it to GPS host application.
+ *
+ *  Parameters :
+ *  @file  : File pointer for GPS char driver
+ *  @data  : Data which needs to be passed to APP
+ *  @size  : Length of the data passesd
+ *  offset :
+ *  Returns  Size of AI2 packet received -  on success
+ *           else suitable error code
+ */
+ssize_t gpsdrv_read(struct file *file, char __user *data, size_t size,
+			loff_t *offset)
+{
+	int len = 0;
+	struct sk_buff *skb = NULL;
+	unsigned long timeout = GPSDRV_READ_TIMEOUT;
+
+	pr_info(" Inside %s", __func__);
+
+	/* Validate input parameters */
+	if ((NULL == file) || (((NULL == data) || (0 == size)))) {
+		pr_err("Invalid input params passed to %s", __func__);
+		return -EINVAL;
+	}
+
+	/* Check if GPS is registered to perform read operation */
+	if (!test_bit(GPS_ST_RUNNING, &hgps->state)) {
+		pr_err("GPS Device is not running");
+		return -EINVAL;
+	}
+
+	/* cannot come here if poll-ed before reading
+	 * if not poll-ed wait on the same wait_q
+	 */
+	timeout = wait_event_interruptible_timeout(hgps->gpsdrv_data_q,
+		!skb_queue_empty(&hgps->rx_list), msecs_to_jiffies(timeout));
+	/* Check for timed out condition */
+	if (0 == timeout) {
+		pr_err("GPS Device Read timed out");
+		return GPS_ERR_TIMEOUT;
+	}
+
+
+	/* hgps->rx_list not empty skb already present */
+	spin_lock(&hgps->lock);
+	skb = skb_dequeue(&hgps->rx_list);
+	spin_unlock(&hgps->lock);
+
+	if (!skb) {
+		pr_err("Dequed SKB is NULL?");
+		return GPS_ERR_UNKNOWN;
+	} else if (skb->len > size) {
+		pr_info("SKB length is Greater than requested size \
+				Returning the available length of SKB");
+
+		if (copy_to_user(data, skb->data, size)) {
+			pr_err(" Unable to copy to user space");
+			/* Queue the skb back to head */
+			spin_lock(&hgps->lock);
+			skb_queue_head(&hgps->rx_list, skb);
+
+			spin_unlock(&hgps->lock);
+			return GPS_ERR_CPY_TO_USR;
+		}
+		skb_pull(skb, size);
+
+		if (skb->len != 0) {
+			spin_lock(&hgps->lock);
+			skb_queue_head(&hgps->rx_list, skb);
+			spin_unlock(&hgps->lock);
+		}
+
+		printk(KERN_DEBUG  "gpsdrv: total size read= %d", size);
+		return size;
+	}
+
+#ifdef VERBOSE
+	for (len = 0; (skb) && (len < skb->len); len++)
+		pr_info(" %x ", skb->data[len]);
+#endif
+
+	/* Forward the data to the user */
+	if (skb->len <= size) {
+		if (copy_to_user(data, skb->data, skb->len)) {
+			pr_err(" Unable to copy to user space");
+			/* Queue the skb back to head */
+			spin_lock(&hgps->lock);
+			skb_queue_head(&hgps->rx_list, skb);
+
+			spin_unlock(&hgps->lock);
+			return GPS_ERR_CPY_TO_USR;
+		}
+	}
+
+	len = skb->len;
+	kfree(skb);
+	printk(KERN_DEBUG  "gpsdrv: total size read= %d", len);
+	return len;
+}
+/* gpsdrv_write Function
+ *  This function will pre-pend the GPS-Channel-9 header to the
+ *  incoming AI2 packet sent from the GPS host application.
+ *
+ *  Parameters :
+ *  @file   : File pointer for GPS char driver
+ *  @data   : AI2 packet data from GPS application
+ *  @size   : Size of the AI2 packet data
+ *  @offset :
+ *  Returns  Size of AI2 packet on success
+ *           else suitable error code
+ */
+ssize_t gpsdrv_write(struct file *file, const char __user *data,
+			 size_t size, loff_t *offset)
+{
+#ifdef VERBOSE
+	long count = 0;
+#endif
+	unsigned char channel = GPS_CH9_PKT_NUMBER; /* GPS Channel number */
+	/* Initialize gpsdrv_event_hdr with write opcode */
+	struct gpsdrv_event_hdr gpsdrv_hdr = { GPS_CH9_OP_WRITE, 0x0000 };
+	struct sk_buff *skb = NULL;
+
+	spin_lock(&hgps->lock);
+	pr_info(" Inside %s", __func__);
+	spin_unlock(&hgps->lock);
+
+	/* Validate input parameters */
+	if ((NULL == file) || (((NULL == data) || (0 == size)))) {
+		pr_err("Invalid input params passed to %s", __func__);
+		return -EINVAL;
+	}
+
+	/* Check if GPS is registered to perform write operation */
+	if (!test_bit(GPS_ST_RUNNING, &hgps->state)) {
+		pr_err("GPS Device is not running");
+		return -EINVAL;
+	}
+
+	if (!hgps->st_write) {
+		pr_err(" Can't write to ST, hgps->st_write null ?");
+		return -EINVAL;
+	}
+
+
+	skb = alloc_skb(size + GPS_CH9_PKT_HDR_SIZE, GFP_ATOMIC);
+	/* Validate Created SKB */
+	if (NULL == skb) {
+		pr_err("Error aaloacting SKB");
+		return -ENOMEM;
+	}
+
+	/* Update chnl-9 information with plen=AI2 pckt size which is "size"*/
+	gpsdrv_hdr.plen = size;
+
+	/* PrePend Channel-9 header to AI2 packet and write to SKB */
+	memcpy(skb_put(skb, 1), &channel, 1);
+	memcpy(skb_put(skb, GPS_CH9_PKT_HDR_SIZE - 1), &gpsdrv_hdr,
+					       GPS_CH9_PKT_HDR_SIZE - 1);
+
+	/* Forward the data from the user space to ST core */
+	if (copy_from_user(skb_put(skb, size), data, size)) {
+		pr_err(" Unable to copy from user space");
+		kfree_skb(skb);
+		return GPS_ERR_CPY_FRM_USR;
+	}
+#ifdef VERBOSE
+	pr_info("start data..");
+	for (count = 0; count < size; count++)
+		printk(" 0x%02x ", skb->data[count]);
+	pr_info("\n..end data");
+#endif
+
+	/* Check if data can be sent to GPS chip
+	 * If not, add it to queue and that can be sent later
+	 */
+	if (0 != hgps->tx_count) {
+		/* If TX Q is empty send current SKB;
+		 *  else, queue current SKB at end of tx_list queue and
+		 *  send first SKB in tx_list queue.
+		 */
+		if (skb_queue_empty(&hgps->tx_list)) {
+			hgps->st_write(skb);
+		} else {
+			spin_lock(&hgps->lock);
+			skb_queue_tail(&hgps->tx_list, skb);
+			hgps->st_write(skb_dequeue(&hgps->tx_list));
+			spin_unlock(&hgps->lock);
+		}
+
+		hgps->tx_count--;
+		/* Check if Tx queue and Tx count not empty and
+		 * schedule wriet tsklet accordingly
+		 */
+		if ((0 != hgps->tx_count) && \
+					(!skb_queue_empty(&hgps->tx_list))) {
+			/* Schedule the Tx-task let */
+			tasklet_schedule(&gpsdrv_tx_tsklet);
+		}
+	} else {
+		/* Add it to TX queue */
+		pr_info(" SKB added to Tx queue");
+		spin_lock(&hgps->lock);
+		skb_queue_tail(&hgps->tx_list, skb);
+		spin_unlock(&hgps->lock);
+	}
+
+	return size;
+}
+
+/** gpsdrv_ioctl Function
+ *  This will peform the functions as directed by the command and command
+ *  argument.
+ *
+ *  Parameters :
+ *  @file  : File pointer for GPS char driver
+ *  @cmd   : IOCTL Command
+ *  @arg   : Command argument for IOCTL command
+ *  Returns  GPS_SUCCESS on success
+ *           else suitable error code
+ */
+static int gpsdrv_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	struct sk_buff *skb = NULL;
+	int		retCode = GPS_SUCCESS;
+	pr_info(" Inside %s", __func__);
+
+	/* Validate input parameters */
+	if ((NULL == file) || (0 == cmd)) {
+		pr_err("Invalid input parameters passed to %s", __func__);
+		return -EINVAL;
+	}
+	/* Check if GPS is registered to perform IOCTL operation */
+	if (!test_bit(GPS_ST_RUNNING, &hgps->state)) {
+		pr_err("GPS Device is not running");
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case TCFLSH:
+		pr_info(" IOCTL TCFLSH invoked with %ld argument", arg);
+	spin_lock(&hgps->lock);
+		switch (arg) {
+		/* purge Rx/Tx SKB list queues depending on arg value */
+		case TCIFLUSH:
+			skb_queue_purge(&hgps->rx_list);
+			break;
+		case TCOFLUSH:
+			skb_queue_purge(&hgps->tx_list);
+			break;
+		case TCIOFLUSH:
+			skb_queue_purge(&hgps->rx_list);
+			skb_queue_purge(&hgps->tx_list);
+			break;
+		default:
+			pr_err("Invalid Command passed for tcflush");
+			retCode = 0;
+			break;
+		}
+		spin_unlock(&hgps->lock);
+		break;
+	case FIONREAD:
+	/* Deque the SKB from the head if rx_list is not empty
+	* And update the argument with skb->len to provide amount of data
+	* available in the available SKB
+	*/
+		spin_lock(&hgps->lock);
+		if (!skb_queue_empty(&hgps->rx_list)) {
+			skb = skb_dequeue(&hgps->rx_list);
+			*(unsigned int *)arg = skb->len;
+			/* Re-Store the SKB for furtur Read operations */
+			skb_queue_head(&hgps->rx_list, skb);
+		} else {
+			*(unsigned int *)arg = 0;
+		}
+		pr_info("returning %d\n", *(unsigned int *)arg);
+		spin_unlock(&hgps->lock);
+		break;
+	default:
+		pr_info("Un-Identified IOCTL %d", cmd);
+		retCode = 0;
+		break;
+	}
+
+	return retCode;
+}
+
+/** gpsdrv_poll Function
+ *  This function will wait till some data is received to the gps driver from ST
+ *
+ *  Parameters :
+ *  @file  : File pointer for GPS char driver
+ *  @wait  : POLL wait information
+ *  Returns  status of POLL on success
+ *           else suitable error code
+ */
+static unsigned int gpsdrv_poll(struct file *file, poll_table *wait)
+{
+	unsigned long mask = 0;
+
+	/* Check if GPS is registered to perform read operation */
+	if (!test_bit(GPS_ST_RUNNING, &hgps->state)) {
+		pr_err("GPS Device is not running");
+		return -EINVAL;
+	}
+
+	/* Wait till data is signalled from gpsdrv_st_recv function
+	 *  with AI2 packet
+	 */
+	poll_wait(file, &hgps->gpsdrv_data_q, wait);
+
+	if (!skb_queue_empty(&hgps->rx_list))
+		mask |= POLLIN;	/* TODO: check app for mask */
+
+	return mask;
+}
+
+/* GPS Char driver function pointers
+ * These functions are called from USER space by pefroming File Operations
+ * on /dev/gps node exposed by this driver during init
+ */
+const struct file_operations gpsdrv_chrdev_ops = {
+	.owner = THIS_MODULE,
+	.open = gpsdrv_open,
+	.read = gpsdrv_read,
+	.write = gpsdrv_write,
+	.ioctl = gpsdrv_ioctl,
+	.poll = gpsdrv_poll,
+	.release = gpsdrv_release,
+};
+
+/*********Functions called during insmod and delmod****************************/
+
+/** gpsdrv_init Function
+ *  This function Initializes the gps driver parametes and exposes
+ *  /dev/gps node to user space
+ *
+ *  Parameters : NULL
+ *  Returns  GPS_SUCCESS on success
+ *           else suitable error code
+ */
+static int __init gpsdrv_init(void)
+{
+
+#ifdef VERBOSE
+	int err = 0;
+#endif
+	pr_info(" Inside %s", __func__);
+
+	/* Allocate local resource memory */
+	hgps = kzalloc(sizeof(struct gpsdrv_data), GFP_KERNEL);
+	if (!(hgps)) {
+		pr_err("Can't allocate GPS data structure");
+		return -ENOMEM;
+	}
+
+	/* Expose the device DEVICE_NAME to user space
+	 * And obtain the major number for the device
+	 */
+	hgps->gpsdrv_major = register_chrdev(0, DEVICE_NAME, \
+						&gpsdrv_chrdev_ops);
+	if (0 > hgps->gpsdrv_major) {
+		pr_err("Error when registering to char dev");
+		kfree(hgps);
+		return GPS_ERR_FAILURE;
+	}
+#ifdef VERBOSE
+	pr_info(" %d: allocated %d, %d", err, hgps->gpsdrv_major, 0);
+#endif
+	/*  ask udev to create device */
+	hgps->gpsdrv_class = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(hgps->gpsdrv_class)) {
+		pr_err(" Something went wrong in class_create");
+		kfree(hgps);
+		unregister_chrdev(hgps->gpsdrv_major, DEVICE_NAME);
+		return GPS_ERR_CLASS;
+	}
+
+	hgps->gpsdrv_dev =
+	  device_create(hgps->gpsdrv_class, NULL, MKDEV(hgps->gpsdrv_major, 0),
+			  NULL, DEVICE_NAME);
+	if (IS_ERR(hgps->gpsdrv_dev)) {
+		pr_err(" Error in class_create");
+		kfree(hgps);
+		unregister_chrdev(hgps->gpsdrv_major, DEVICE_NAME);
+		class_unregister(hgps->gpsdrv_class);
+		class_destroy(hgps->gpsdrv_class);
+		return GPS_ERR_CLASS;
+	}
+
+	/* Initialize wait queue, skb queue head and
+	 * registration complete strucuture
+	 */
+	skb_queue_head_init(&hgps->rx_list);
+	skb_queue_head_init(&hgps->tx_list);
+	init_completion(&hgps->gpsdrv_reg_completed);
+	init_waitqueue_head(&hgps->gpsdrv_data_q);
+	spin_lock_init(&hgps->lock);
+
+	return GPS_SUCCESS;
+}
+
+/** gpsdrv_exit Function
+ *  This function Destroys the gps driver parametes and /dev/gps node
+ *
+ *  Parameters : NULL
+ *  Returns   NULL
+ */
+static void __exit gpsdrv_exit(void)
+{
+	pr_info(" Inside %s", __func__);
+	pr_info(" Bye.. freeing up %d", hgps->gpsdrv_major);
+
+	skb_queue_purge(&hgps->rx_list);
+	skb_queue_purge(&hgps->tx_list);
+	device_destroy(hgps->gpsdrv_class, MKDEV(hgps->gpsdrv_major, 0));
+
+	class_unregister(hgps->gpsdrv_class);
+	class_destroy(hgps->gpsdrv_class);
+
+	unregister_chrdev(hgps->gpsdrv_major, DEVICE_NAME);
+	tasklet_kill(&gpsdrv_tx_tsklet);
+	kfree(hgps);
+}
+
+module_init(gpsdrv_init);
+module_exit(gpsdrv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ti-st/gps_drv.h b/drivers/staging/ti-st/gps_drv.h
new file mode 100644
index 0000000..620559e
--- /dev/null
+++ b/drivers/staging/ti-st/gps_drv.h
@@ -0,0 +1,91 @@
+/*
+ *   GPS Char Driver for Texas Instrument's Connectivity Chip.
+ *   Copyright (C) 2009 Texas Instruments
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2 as
+ *   published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef GPSDRV_H
+#define GPSDRV_H
+
+
+void gpsdrv_tsklet_write(unsigned long data);
+
+/* List of error codes returned by the gps driver*/
+enum {
+	GPS_ERR_FAILURE = -1,	/* check struct */
+	GPS_SUCCESS,
+	GPS_ERR_PENDING = -5,	/* to call reg_complete_cb */
+	GPS_ERR_ALREADY,	/* already registered */
+	GPS_ERR_INPROGRESS,
+	GPS_ERR_NOPROTO,	/* protocol not supported */
+	GPS_ERR_CLASS = -15,
+	GPS_ERR_CPY_TO_USR,
+	GPS_ERR_CPY_FRM_USR,
+	GPS_ERR_TIMEOUT,
+	GPS_ERR_UNKNOWN,
+};
+
+/* Channel-9 details for GPS */
+#define GPS_CH9_PKT_HDR_SIZE		4
+#define GPS_CH9_PKT_NUMBER		0x9
+#define GPS_CH9_OP_WRITE		0x1
+#define GPS_CH9_OP_READ			0x2
+#define GPS_CH9_OP_COMPLETED_EVT	0x3
+
+/* Macros for Syncronising GPS registration and other R/W/ICTL operations */
+#define GPS_ST_REGISTERED		0
+#define GPS_ST_RUNNING			1
+
+/* Read time out defined to 10 seconds */
+#define GPSDRV_READ_TIMEOUT		10000
+/* Reg time out defined to 6 seconds */
+#define GPSDRV_REG_TIMEOUT		6000
+
+
+struct gpsdrv_event_hdr {
+	uint8_t opcode;
+	uint16_t plen;
+} __attribute__ ((packed));
+
+/* BT driver operation structure */
+struct gpsdrv_data {
+
+	int gpsdrv_major;		/* GPS major number */
+	struct class *gpsdrv_class;	/* GPS class during class_create */
+	struct device *gpsdrv_dev;	/* GPS dev during device_create */
+
+	struct completion gpsdrv_reg_completed;
+		/*comepletion handler to synchronize gpsdrv_chrdev_open */
+	char streg_cbdata;	/* ST registration callback  status */
+
+	unsigned long state;
+		/* used locally,to maintain various GPS driver status */
+	unsigned char tx_count;	/* Count value which gives number of Tx GPS
+				 * commands that can be sent to GPS chip */
+
+	long (*st_write) (struct sk_buff *skb);
+				/* write function pointer of ST driver */
+	struct sk_buff_head rx_list;	/* Rx data SKB queue */
+	struct sk_buff_head tx_list;	/* Tx data SKB queue */
+
+	wait_queue_head_t gpsdrv_data_q;
+			/* Used to syncronize read call and poll */
+
+	spinlock_t lock;
+		/* spin lock data for safe-gaurding operations on SKB */
+
+};
+
+#endif /*GPS_H */
-- 
1.5.4.3





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] drivers: staging: GPS protocol driver for wl128x
  2010-05-04 16:25 [PATCH] drivers: staging: GPS protocol driver for wl128x Pavan Savoy
@ 2010-05-05 11:11 ` Alan Cox
  2010-05-05 16:04   ` Savoy, Pavan
  2010-05-06 20:30   ` Savoy, Pavan
  0 siblings, 2 replies; 6+ messages in thread
From: Alan Cox @ 2010-05-05 11:11 UTC (permalink / raw)
  To: pavan_savoy; +Cc: greg, linux-kernel

On Tue, 4 May 2010 21:55:43 +0530 (IST)
Pavan Savoy <pavan_savoy@ti.com> wrote:

> Greg, Alan,
> 
> Just to complete the circle on N_TI_WL, find below the GPS driver which makes use of the shared transport line discipline.
> 
> This driver provides a TTY line character device to application/middle-ware running on host, as if the device is directly connected over UART to a GPS chip.

This doesn't appear to be a tty device ?

> Almost all actions that can be done on a /dev/ttySx can be done on this /dev/tigps device.

Hardly true. A tty driver has a very precisely defined set of behaviours
and a lot of ioctls and interfaces your driver doesn't. Our gps
interfaces are only tty drivers because historically they were plugged
into serial ports so I'm not sure the 'not a tty' bit actually matters.

Codewise its the same as all the rest - only one instance possible and
poking around in globals with no visible or documented locking.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH] drivers: staging: GPS protocol driver for wl128x
  2010-05-05 11:11 ` Alan Cox
@ 2010-05-05 16:04   ` Savoy, Pavan
  2010-05-06 20:30   ` Savoy, Pavan
  1 sibling, 0 replies; 6+ messages in thread
From: Savoy, Pavan @ 2010-05-05 16:04 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel

Alan,

 
----------------
Thanks & Regards,
Pavan Savoy | x0099669
 
> -----Original Message-----
> From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk]
> Sent: Wednesday, May 05, 2010 6:12 AM
> To: Savoy, Pavan
> Cc: greg; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] drivers: staging: GPS protocol driver for wl128x
> 
> On Tue, 4 May 2010 21:55:43 +0530 (IST)
> Pavan Savoy <pavan_savoy@ti.com> wrote:
> 
> > Greg, Alan,
> >
> > Just to complete the circle on N_TI_WL, find below the GPS driver which makes use of the shared transport
> line discipline.
> >
> > This driver provides a TTY line character device to application/middle-ware running on host, as if the
> device is directly connected over UART to a GPS chip.
> 
> This doesn't appear to be a tty device ?

A typo here, I meant "TTY like" character device, and it not certainly a character device.

> 
> > Almost all actions that can be done on a /dev/ttySx can be done on this /dev/tigps device.
> 
> Hardly true. A tty driver has a very precisely defined set of behaviours
> and a lot of ioctls and interfaces your driver doesn't. Our gps
> interfaces are only tty drivers because historically they were plugged
> into serial ports so I'm not sure the 'not a tty' bit actually matters.

Yes. I agree, and hence mentioned almost all.

> Codewise its the same as all the rest - only one instance possible and
> poking around in globals with no visible or documented locking.

Yes, and this is the reason, I posted this patch.
BT and GPS had to communicate over a single UART, and this is the reason the N_TI_WL line discipline exists.
With this sort of architecture, how can I accommodate multi-device support? To avoid this single device limits?

Also, what is that you are exactly looking for regarding locking.
Please suggest.

Thanks.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH] drivers: staging: GPS protocol driver for wl128x
  2010-05-05 11:11 ` Alan Cox
  2010-05-05 16:04   ` Savoy, Pavan
@ 2010-05-06 20:30   ` Savoy, Pavan
  2010-05-06 21:34     ` Pavan Savoy
  1 sibling, 1 reply; 6+ messages in thread
From: Savoy, Pavan @ 2010-05-06 20:30 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel, Menon, Nishanth


Alan,
 
> -----Original Message-----
> From: Savoy, Pavan
> Sent: Wednesday, May 05, 2010 11:04 AM
> To: 'Alan Cox'
> Cc: greg; linux-kernel@vger.kernel.org
> Subject: RE: [PATCH] drivers: staging: GPS protocol driver for wl128x
> 
> Alan,
> 
> 
> ----------------
> Thanks & Regards,
> Pavan Savoy | x0099669
> 
> > -----Original Message-----
> > From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk]
> > Sent: Wednesday, May 05, 2010 6:12 AM
> > To: Savoy, Pavan
> > Cc: greg; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH] drivers: staging: GPS protocol driver for wl128x
> >
> > On Tue, 4 May 2010 21:55:43 +0530 (IST)
> > Pavan Savoy <pavan_savoy@ti.com> wrote:
> >
> > > Greg, Alan,
> > >
> > > Just to complete the circle on N_TI_WL, find below the GPS driver which makes use of the shared
> transport
> > line discipline.
> > >
> > > This driver provides a TTY line character device to application/middle-ware running on host, as if the
> > device is directly connected over UART to a GPS chip.
> >
> > This doesn't appear to be a tty device ?
> 
> A typo here, I meant "TTY like" character device, and it not certainly a character device.
> 
> >
> > > Almost all actions that can be done on a /dev/ttySx can be done on this /dev/tigps device.
> >
> > Hardly true. A tty driver has a very precisely defined set of behaviours
> > and a lot of ioctls and interfaces your driver doesn't. Our gps
> > interfaces are only tty drivers because historically they were plugged
> > into serial ports so I'm not sure the 'not a tty' bit actually matters.
> 
> Yes. I agree, and hence mentioned almost all.
> 
> > Codewise its the same as all the rest - only one instance possible and
> > poking around in globals with no visible or documented locking.

To support this multiple device thingy and avoid the single device limit, I plan to do something like this,

The ST driver would be platform_device - as it is already. ST's probe would do the ldisc registration, and also do the dev_set_drvdata of all the internal data (Tx queues, locks, list of protocols) on this device.

Apart from this the BT, FM and GPS would also further be platform devices, and then,
In the dev.platform_data of each of these BT, FM and GPS devices, I will enter the "parent ST device", these protocols want to attach themselves to.

And in probe of the driver for each of these BT, FM and GPS devices, I will do the same "st_register" where in now I can access the ST related data by retrieving the internal using the parent device.

Examples:
Here are the 2 ST platform devices,
struct platform_device st_device_0 = {
        .name = "ST_DEV_0",
        .id = -1,
        .dev.platform_data = &array,
        .dev.release = any_device_release,
};
struct platform_device st_device_1 = {
        .name = "ST_DEV_1",
        .id = -1,
        .dev.platform_data = &array,
        .dev.release = any_device_release,
};

BT attaching itself to ST_DEV_0,
static struct protocol_platform_data bt_data = {
        .parent_dev = &st_device_0,
        .name = "BT",
};

static struct platform_device bt_device = {
        .name = "BT",
        .id = -1,
        .dev.platform_data = &bt_data,
        .dev.release = bt_device_release,
};

And FM attaching itself to - ST_DEV_1,
static struct protocol_platform_data fm_data = {
        .parent_dev = &st_device_1,
        .name = "FM",
};
static struct platform_device fm_device = {
        .name = "FM",
        .id = -1,
        .dev.platform_data = &fm_data,
        .dev.release = fm_device_release,
};

My "ST_REGISTER" would now look like,
int st_register(struct protocol_platform_data *data)
{
        struct st_data_s *st_data;
        struct platform_device *parent = data->parent_dev;

        st_data = dev_get_drvdata(&parent->dev);

        printk("%s registering into %s\n", data->name, parent->name);

        printk("data got is %s\n", st_data->name);
        st_data->name = "Changed Name";
        return 0;
}
EXPORT_SYMBOL(st_register);


However, I would need to have a ST platform driver for each of my such ST platform devices (ST_DEV_0, ST_DEV_1).

It does seem a big-re-write of the probing/registration logic..
So, How does this sound?

Please suggest.


> Yes, and this is the reason, I posted this patch.
> BT and GPS had to communicate over a single UART, and this is the reason the N_TI_WL line discipline exists.
> With this sort of architecture, how can I accommodate multi-device support? To avoid this single device
> limits?
> 
> Also, what is that you are exactly looking for regarding locking.
> Please suggest.
> 
> Thanks.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH] drivers: staging: GPS protocol driver for wl128x
  2010-05-06 20:30   ` Savoy, Pavan
@ 2010-05-06 21:34     ` Pavan Savoy
  2010-06-11 12:25       ` Pavan Savoy
  0 siblings, 1 reply; 6+ messages in thread
From: Pavan Savoy @ 2010-05-06 21:34 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel, NishanthMenon



--- On Fri, 7/5/10, Savoy, Pavan <pavan_savoy@ti.com> wrote:

> From: Savoy, Pavan <pavan_savoy@ti.com>
> Subject: RE: [PATCH] drivers: staging: GPS protocol driver for wl128x
> To: "Alan Cox" <alan@lxorguk.ukuu.org.uk>
> Cc: "greg" <gregkh@suse.de>, "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>, "Menon, Nishanth" <nm@ti.com>
> Date: Friday, 7 May, 2010, 2:00 AM
> 
> Alan,
>  
> > -----Original Message-----
> > From: Savoy, Pavan
> > Sent: Wednesday, May 05, 2010 11:04 AM
> > To: 'Alan Cox'
> > Cc: greg; linux-kernel@vger.kernel.org
> > Subject: RE: [PATCH] drivers: staging: GPS protocol
> driver for wl128x
> > 
> > Alan,
> > 
> > 
> > ----------------
> > Thanks & Regards,
> > Pavan Savoy | x0099669
> > 
> > > -----Original Message-----
> > > From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk]
> > > Sent: Wednesday, May 05, 2010 6:12 AM
> > > To: Savoy, Pavan
> > > Cc: greg; linux-kernel@vger.kernel.org
> > > Subject: Re: [PATCH] drivers: staging: GPS
> protocol driver for wl128x
> > >
> > > On Tue, 4 May 2010 21:55:43 +0530 (IST)
> > > Pavan Savoy <pavan_savoy@ti.com>
> wrote:
> > >
> > > > Greg, Alan,
> > > >
> > > > Just to complete the circle on N_TI_WL, find
> below the GPS driver which makes use of the shared
> > transport
> > > line discipline.
> > > >
> > > > This driver provides a TTY line character
> device to application/middle-ware running on host, as if
> the
> > > device is directly connected over UART to a GPS
> chip.
> > >
> > > This doesn't appear to be a tty device ?
> > 
> > A typo here, I meant "TTY like" character device, and
> it not certainly a character device.
> > 
> > >
> > > > Almost all actions that can be done on a
> /dev/ttySx can be done on this /dev/tigps device.
> > >
> > > Hardly true. A tty driver has a very precisely
> defined set of behaviours
> > > and a lot of ioctls and interfaces your driver
> doesn't. Our gps
> > > interfaces are only tty drivers because
> historically they were plugged
> > > into serial ports so I'm not sure the 'not a tty'
> bit actually matters.
> > 
> > Yes. I agree, and hence mentioned almost all.
> > 
> > > Codewise its the same as all the rest - only one
> instance possible and
> > > poking around in globals with no visible or
> documented locking.
> 
> To support this multiple device thingy and avoid the single
> device limit, I plan to do something like this,
> 
> The ST driver would be platform_device - as it is already.
> ST's probe would do the ldisc registration, and also do the
> dev_set_drvdata of all the internal data (Tx queues, locks,
> list of protocols) on this device.
> 
> Apart from this the BT, FM and GPS would also further be
> platform devices, and then,
> In the dev.platform_data of each of these BT, FM and GPS
> devices, I will enter the "parent ST device", these
> protocols want to attach themselves to.
> 
> And in probe of the driver for each of these BT, FM and GPS
> devices, I will do the same "st_register" where in now I can
> access the ST related data by retrieving the internal using
> the parent device.
> 
> Examples:
> Here are the 2 ST platform devices,
> struct platform_device st_device_0 = {
>         .name = "ST_DEV_0",
>         .id = -1,
>         .dev.platform_data =
> &array,
>         .dev.release =
> any_device_release,
> };
> struct platform_device st_device_1 = {
>         .name = "ST_DEV_1",
>         .id = -1,
>         .dev.platform_data =
> &array,
>         .dev.release =
> any_device_release,
> };
> 
> BT attaching itself to ST_DEV_0,
> static struct protocol_platform_data bt_data = {
>         .parent_dev =
> &st_device_0,
>         .name = "BT",
> };
> 
> static struct platform_device bt_device = {
>         .name = "BT",
>         .id = -1,
>         .dev.platform_data =
> &bt_data,
>         .dev.release =
> bt_device_release,
> };
> 
> And FM attaching itself to - ST_DEV_1,
> static struct protocol_platform_data fm_data = {
>         .parent_dev =
> &st_device_1,
>         .name = "FM",
> };
> static struct platform_device fm_device = {
>         .name = "FM",
>         .id = -1,
>         .dev.platform_data =
> &fm_data,
>         .dev.release =
> fm_device_release,
> };
> 
> My "ST_REGISTER" would now look like,
> int st_register(struct protocol_platform_data *data)
> {
>         struct st_data_s *st_data;
>         struct platform_device *parent
> = data->parent_dev;
> 
>         st_data =
> dev_get_drvdata(&parent->dev);
> 
>         printk("%s registering into
> %s\n", data->name, parent->name);
> 
>         printk("data got is %s\n",
> st_data->name);
>         st_data->name = "Changed
> Name";
>         return 0;
> }
> EXPORT_SYMBOL(st_register);
> 
> 
> However, I would need to have a ST platform driver for each
> of my such ST platform devices (ST_DEV_0, ST_DEV_1).
> 
> It does seem a big-re-write of the probing/registration
> logic..
> So, How does this sound?
> 
> Please suggest.

Just to add, I would have 1 more problem to address, How can I link up my tty->disc_data with my platform-data ?
On registering ldisc_ops I would have liked to have an _private data sent in during tty_open/close/ioctl calls - which currently ldisc_ops doesn't support.

> 
> > Yes, and this is the reason, I posted this patch.
> > BT and GPS had to communicate over a single UART, and
> this is the reason the N_TI_WL line discipline exists.
> > With this sort of architecture, how can I accommodate
> multi-device support? To avoid this single device
> > limits?
> > 
> > Also, what is that you are exactly looking for
> regarding locking.
> > Please suggest.
> > 
> > Thanks.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 



^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH] drivers: staging: GPS protocol driver for wl128x
  2010-05-06 21:34     ` Pavan Savoy
@ 2010-06-11 12:25       ` Pavan Savoy
  0 siblings, 0 replies; 6+ messages in thread
From: Pavan Savoy @ 2010-06-11 12:25 UTC (permalink / raw)
  To: Alan Cox; +Cc: greg, linux-kernel

Alan, (slightly long mail warning..)

as I mentioned before, the problem is how can I know which platform device's registration caused the tty_open to be called ?

Background: [apart from the mail chain below...]
A platform driver by name ST_0 allows registration of certain protocol driver like BT_0 to be registered onto it, and use it as the transport.

This plat driver ST_O now signals the user-space to open up a TTY device and install the ldisc on top of it. (ldisc being ST_0's registered ldisc during it's plat probe).

Now the plat driver's tty_open previously registered is called, but here lies the problem - On what basis do I know that it was because of ST_0 and also How can I send the device number 'x' information in ttySx for user-space application to open/tiocsetd on that device.


All these problems would be solved, if only we could open/tiocsetd a ldisc from the kernel space - basically the ability to claim/use a TTY interface.
something like,

tty_register_ldisc(N_TI_WL, &ldisc_ops, UART_NUM_1);
tty_set_ldisc(); from ldisc drivers itself.. 

please comment...


> Here are the 2 ST platform devices,
> struct platform_device st_device_0 = {
>         .name = "ST_DEV_0",
>         .id = -1,
>         .dev.platform_data =
> &array,
>         .dev.release =
> any_device_release,
> };
> struct platform_device st_device_1 = {
>         .name = "ST_DEV_1",
>         .id = -1,
>         .dev.platform_data =
> &array,
>         .dev.release =
> any_device_release,
> };
>
> BT attaching itself to ST_DEV_0,
> static struct protocol_platform_data bt_data = {
>         .parent_dev =
> &st_device_0,
>         .name = "BT",
> };
>
> static struct platform_device bt_device = {
>         .name = "BT",
>         .id = -1,
>         .dev.platform_data =
> &bt_data,
>         .dev.release =
> bt_device_release,
> };
>
> And FM attaching itself to - ST_DEV_1,
> static struct protocol_platform_data fm_data = {
>         .parent_dev =
> &st_device_1,
>         .name = "FM",
> };
> static struct platform_device fm_device = {
>         .name = "FM",
>         .id = -1,
>         .dev.platform_data =
> &fm_data,
>         .dev.release =
> fm_device_release,
> };
>
> My "ST_REGISTER" would now look like,
> int st_register(struct protocol_platform_data *data)
> {
>         struct st_data_s *st_data;
>         struct platform_device *parent
> = data->parent_dev;
>
>         st_data =
> dev_get_drvdata(&parent->dev);
>
>         printk("%s registering into
> %s\n", data->name, parent->name);
>
>         printk("data got is %s\n",
> st_data->name);
>         st_data->name = "Changed
> Name";
>         return 0;
> }
> EXPORT_SYMBOL(st_register);



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-06-11 12:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-04 16:25 [PATCH] drivers: staging: GPS protocol driver for wl128x Pavan Savoy
2010-05-05 11:11 ` Alan Cox
2010-05-05 16:04   ` Savoy, Pavan
2010-05-06 20:30   ` Savoy, Pavan
2010-05-06 21:34     ` Pavan Savoy
2010-06-11 12:25       ` Pavan Savoy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®