Commit c6465799 authored by Steven Toth's avatar Steven Toth Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (8262): sms1xxx: remove smschar.o

parent 464a77dd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
# Makefile for the kernel MDTV driver
#

smscore-objs := smschar.o smscoreapi.o
smscore-objs := smscoreapi.o

obj-$(CONFIG_MDTV_SIANO_STELLAR_COMMON) += smscore.o
obj-$(CONFIG_MDTV_SIANO_STELLAR_USB) += smsusb.o

drivers/media/mdtv/smschar.c

deleted100644 → 0
+0 −577
Original line number Diff line number Diff line
/*!

	\file		smschar.c

	\brief		Implementation of smscore client for cdev based access

    \par 		Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.

    \par 		This program is free software; you can redistribute it and/or modify
			it under the terms of the GNU General Public License version 3 as
			published by the Free Software Foundation;

			Software distributed under the License is distributed on an "AS
			IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
			implied.

	\author		Anatoly Greenblat

*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/kernel.h>		/* printk() */
#include <linux/fs.h>			/* everything... */
#include <linux/types.h>		/* size_t */
#include <linux/cdev.h>
#include <linux/sched.h>
#include <asm/system.h>			/* cli(), *_flags */
#include <asm/uaccess.h>		/* copy_*_user */

#include "smskdefs.h" // page, scatterlist, kmutex
#include "smscoreapi.h"
#include "smstypes.h"

#include "smscharioctl.h"

#define SMS_CHR_MAX_Q_LEN	10 // max number of packets allowed to be pending on queue
#define SMSCHAR_NR_DEVS		7

typedef struct _smschar_device
{
	struct cdev			cdev;				//!<  Char device structure - kernel's device model representation

	wait_queue_head_t	waitq;					/* Processes waiting */
	spinlock_t			lock;				//!< critical section
	int					pending_count;
	struct list_head	pending_data;		//!< list of pending data

	smscore_buffer_t	*currentcb;

	int					device_index;

	smscore_device_t	*coredev;
	smscore_client_t	*smsclient;
} smschar_device_t;

//!  Holds the major number of the device node. may be changed at load time.
int smschar_major = 251;

//!  Holds the first minor number of the device node. may be changed at load time.
int smschar_minor = 0;

// macros that allow the load time parameters change
module_param ( smschar_major, int, S_IRUGO );
module_param ( smschar_minor, int, S_IRUGO );

#ifdef SMSCHAR_DEBUG

	#undef PERROR
#  define PERROR(fmt, args...) printk( KERN_INFO "smschar error: line %d- %s(): " fmt,__LINE__,  __FUNCTION__, ## args)
	#undef PWARNING
#  define PWARNING(fmt, args...) printk( KERN_INFO "smschar warning: line %d- %s(): " fmt,__LINE__,  __FUNCTION__, ## args)
	#undef PDEBUG					/* undef it, just in case */
#  define PDEBUG(fmt, args...)	printk( KERN_INFO "smschar - %s(): " fmt, __FUNCTION__, ## args)

#else /* not debugging: nothing */

	#define PDEBUG(fmt, args...)
	#define PERROR(fmt, args...)
	#define PWARNING(fmt, args...)

#endif

smschar_device_t smschar_devices[SMSCHAR_NR_DEVS];
static int g_smschar_inuse = 0;

/**
 * unregisters sms client and returns all queued buffers
 *
 * @param dev pointer to the client context (smschar parameters block)
 *
 */
void smschar_unregister_client(smschar_device_t* dev)
{
	unsigned long flags;

	if (dev->coredev && dev->smsclient)
	{
		wake_up_interruptible(&dev->waitq);

		spin_lock_irqsave(&dev->lock, flags);

		while (!list_empty(&dev->pending_data))
		{
			smscore_buffer_t *cb = (smscore_buffer_t *) dev->pending_data.next;
			list_del(&cb->entry);

			smscore_putbuffer(dev->coredev, cb);

			dev->pending_count --;
		}

		if (dev->currentcb)
		{
			smscore_putbuffer(dev->coredev, dev->currentcb);
			dev->currentcb = NULL;
			dev->pending_count --;
		}

		smscore_unregister_client(dev->smsclient);
		dev->smsclient = NULL;

		spin_unlock_irqrestore(&dev->lock, flags);
	}
}

/**
 * queues incoming buffers into buffers queue
 *
 * @param context pointer to the client context (smschar parameters block)
 * @param cb pointer to incoming buffer descriptor
 *
 * @return 0 on success, <0 on queue overflow.
 */
int smschar_onresponse(void *context, smscore_buffer_t *cb)
{
	smschar_device_t *dev = context;
	unsigned long flags;

	spin_lock_irqsave(&dev->lock, flags);

	if (dev->pending_count > SMS_CHR_MAX_Q_LEN)
	{
		spin_unlock_irqrestore(&dev->lock, flags);
		return -EBUSY;
	}

	dev->pending_count ++;

	// if data channel, remove header
	if (dev->device_index)
	{
		cb->size -= sizeof(SmsMsgHdr_ST);
		cb->offset += sizeof(SmsMsgHdr_ST);
	}

	list_add_tail(&cb->entry, &dev->pending_data);
	spin_unlock_irqrestore(&dev->lock, flags);

	if (waitqueue_active(&dev->waitq))
		wake_up_interruptible(&dev->waitq);

	return 0;
}

/**
 * handles device removal event
 *
 * @param context pointer to the client context (smschar parameters block)
 *
 */
void smschar_onremove(void *context)
{
	smschar_device_t *dev = (smschar_device_t *) context;

	smschar_unregister_client(dev);
	dev->coredev = NULL;
}

/**
 * registers client associated with the node
 *
 * @param inode Inode concerned.
 * @param file File concerned.
 *
 * @return 0 on success, <0 on error.
 */
int smschar_open (struct inode *inode, struct file *file)
{
	smschar_device_t *dev = container_of(inode->i_cdev, smschar_device_t, cdev);
	int rc = -ENODEV;

	PDEBUG("entering index %d\n", dev->device_index);

	if (dev->coredev)
	{
		smsclient_params_t params;

		params.initial_id = dev->device_index ? dev->device_index : SMS_HOST_LIB;
		params.data_type = dev->device_index ? MSG_SMS_DAB_CHANNEL : 0;
		params.onresponse_handler = smschar_onresponse;
		params.onremove_handler = smschar_onremove;
		params.context = dev;

		rc = smscore_register_client(dev->coredev, &params, &dev->smsclient);
		if (!rc)
		{
			file->private_data = dev;
		}
	}

	PDEBUG("exiting, rc %d\n", rc);

	return rc;
}

/**
 * unregisters client associated with the node
 *
 * @param inode Inode concerned.
 * @param file File concerned.
 *
 */
int smschar_release(struct inode *inode, struct file *file)
{
	smschar_unregister_client(file->private_data);

	PDEBUG("exiting\n");

	return 0;
}

/**
 * copies data from buffers in incoming queue into a user buffer
 *
 * @param file File structure.
 * @param buf Source buffer.
 * @param count Size of source buffer.
 * @param f_pos Position in file (ignored).
 *
 * @return Number of bytes read, or <0 on error.
 */
ssize_t smschar_read ( struct file * file, char __user * buf, size_t count, loff_t * f_pos )
{
	smschar_device_t *dev = file->private_data;
	unsigned long flags;
	int copied = 0;

	if (!dev->coredev || !dev->smsclient)
	{
		PERROR("no client\n");
		return -ENODEV;
	}

	while (copied != count)
	{
		if (0 > wait_event_interruptible(dev->waitq, !list_empty(&dev->pending_data)))
		{
			PERROR("wait_event_interruptible error\n");
			return -ENODEV;
		}

		if (!dev->smsclient)
		{
			PERROR("no client\n");
			return -ENODEV;
		}

		spin_lock_irqsave(&dev->lock, flags);

		while (!list_empty(&dev->pending_data) && (copied != count))
		{
			smscore_buffer_t *cb = (smscore_buffer_t *) dev->pending_data.next;
			int actual_size = min(((int) count - copied), cb->size);

			copy_to_user(&buf[copied], &((char*)cb->p)[cb->offset], actual_size);

			copied += actual_size;
			cb->offset += actual_size;
			cb->size -= actual_size;

			if (!cb->size)
			{
				list_del(&cb->entry);
				smscore_putbuffer(dev->coredev, cb);

				dev->pending_count --;
			}
		}

		spin_unlock_irqrestore(&dev->lock, flags);
	}

	return copied;
}

/**
 * sends the buffer to the associated device
 *
 * @param file File structure.
 * @param buf Source buffer.
 * @param count Size of source buffer.
 * @param f_pos Position in file (ignored).
 *
 * @return Number of bytes read, or <0 on error.
 */
ssize_t smschar_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{
	smschar_device_t *dev = file->private_data;
	void *buffer;

	if (!dev->smsclient)
	{
		PERROR("no client\n");
		return -ENODEV;
	}

	buffer = kmalloc(ALIGN(count, SMS_ALLOC_ALIGNMENT) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
	if (buffer)
	{
		void *msg_buffer = (void*) SMS_ALIGN_ADDRESS(buffer);

		if (!copy_from_user(msg_buffer, buf, count))
			smsclient_sendrequest(dev->smsclient, msg_buffer, count);
		else
			count = 0;

		kfree(buffer);
	}

	return count;
}

int smschar_mmap(struct file *file, struct vm_area_struct *vma)
{
	smschar_device_t *dev = file->private_data;
	return smscore_map_common_buffer(dev->coredev, vma);
}

/**
 * waits until buffer inserted into a queue. when inserted buffer offset are reported
 * to the calling process. previously reported buffer is returned to smscore pool
 *
 * @param dev pointer to smschar parameters block
 * @param touser pointer to a structure that receives incoming buffer offsets
 *
 * @return 0 on success, <0 on error.
 */
int smschar_wait_get_buffer(smschar_device_t* dev, smschar_buffer_t* touser)
{
	unsigned long flags;
	int rc;

	spin_lock_irqsave(&dev->lock, flags);

	if (dev->currentcb)
	{
		smscore_putbuffer(dev->coredev, dev->currentcb);
		dev->currentcb = NULL;
		dev->pending_count --;
	}

	spin_unlock_irqrestore(&dev->lock, flags);

	rc = wait_event_interruptible(dev->waitq, !list_empty(&dev->pending_data));
	if (rc < 0)
	{
		PERROR("wait_event_interruptible error\n");
		return rc;
	}

	if (!dev->smsclient)
	{
		PERROR("no client\n");
		return -ENODEV;
	}

	spin_lock_irqsave(&dev->lock, flags);

	if (!list_empty(&dev->pending_data))
	{
		smscore_buffer_t *cb = (smscore_buffer_t *) dev->pending_data.next;

		touser->offset = cb->offset_in_common + cb->offset;
		touser->size = cb->size;

		list_del(&cb->entry);

		dev->currentcb = cb;
	}
	else
	{
		touser->offset = 0;
		touser->size = 0;
	}

	spin_unlock_irqrestore(&dev->lock, flags);

	return 0;
}

int smschar_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	smschar_device_t *dev = file->private_data;
	void __user *up = (void __user *) arg;

	if (!dev->coredev || !dev->smsclient)
	{
		PERROR("no client\n");
		return -ENODEV;
	}

	switch(cmd)
	{
		case SMSCHAR_SET_DEVICE_MODE:
			return smscore_set_device_mode(dev->coredev, (int) arg);

		case SMSCHAR_GET_DEVICE_MODE:
		{
			if (put_user(smscore_get_device_mode(dev->coredev), (int*) up))
				return -EFAULT;

			break;
		}

		case SMSCHAR_GET_BUFFER_SIZE:
		{
			if (put_user(smscore_get_common_buffer_size(dev->coredev), (int*) up))
				return -EFAULT;

			break;
		}

		case SMSCHAR_WAIT_GET_BUFFER:
		{
			smschar_buffer_t touser;
			int rc;

			rc = smschar_wait_get_buffer(dev, &touser);
			if (rc < 0)
				return rc;

			if (copy_to_user(up, &touser, sizeof(smschar_buffer_t)))
				return -EFAULT;

			break;
		}

		default:
			return -ENOIOCTLCMD;
	}

	return 0;
}

struct file_operations smschar_fops =
{
	.owner = THIS_MODULE,
	.read = smschar_read,
	.write = smschar_write,
	.open = smschar_open,
	.release = smschar_release,
	.mmap = smschar_mmap,
	.ioctl = smschar_ioctl,
};

static int smschar_setup_cdev ( smschar_device_t *dev, int index )
{
	int rc, devno = MKDEV ( smschar_major, smschar_minor + index );

	cdev_init ( &dev->cdev, &smschar_fops );

	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &smschar_fops;

	kobject_set_name(&dev->cdev.kobj, "Siano_sms%d", index);

	rc = cdev_add ( &dev->cdev, devno, 1 );

	PDEBUG("exiting %p %d, rc %d\n", dev, index, rc);

	return rc;
}

/**
 * smschar callback that called when device plugged in/out. the function
 * register or unregisters char device interface according to plug in/out
 *
 * @param coredev pointer to device that is being plugged in/out
 * @param device pointer to system device object
 * @param arrival 1 on plug-on, 0 othewise
 *
 * @return 0 on success, <0 on error.
 */
int smschar_hotplug(smscore_device_t* coredev, struct device* device, int arrival)
{
	int rc = 0, i;

	PDEBUG("entering %d\n", arrival);

	if (arrival)
	{
		// currently only 1 instance supported
		if (!g_smschar_inuse)
		{
			/* data notification callbacks assignment */
			memset ( smschar_devices, 0, SMSCHAR_NR_DEVS * sizeof ( smschar_device_t ) );

			/* Initialize each device. */
			for (i = 0; i < SMSCHAR_NR_DEVS; i++)
			{
				smschar_setup_cdev ( &smschar_devices[i], i );

				INIT_LIST_HEAD(&smschar_devices[i].pending_data);
				spin_lock_init(&smschar_devices[i].lock);
				init_waitqueue_head(&smschar_devices[i].waitq);

				smschar_devices[i].coredev = coredev;
				smschar_devices[i].device_index = i;
			}

			g_smschar_inuse = 1;
		}
	}
	else
	{
		// currently only 1 instance supported
		if (g_smschar_inuse)
		{
			/* Get rid of our char dev entries */
			for(i = 0; i < SMSCHAR_NR_DEVS; i++)
				cdev_del(&smschar_devices[i].cdev);

			g_smschar_inuse = 0;
		}
	}

	PDEBUG("exiting, rc %d\n", rc);

	return rc;					/* succeed */
}

int smschar_initialize(void)
{
	dev_t devno = MKDEV ( smschar_major, smschar_minor );
	int rc;

	if(smschar_major)
	{
		rc = register_chrdev_region ( devno, SMSCHAR_NR_DEVS, "smschar" );
	}
	else
	{
		rc = alloc_chrdev_region ( &devno, smschar_minor, SMSCHAR_NR_DEVS, "smschar" );
		smschar_major = MAJOR ( devno );
	}

	if (rc < 0)
	{
		PWARNING (  "smschar: can't get major %d\n", smschar_major );
		return rc;
	}

	return smscore_register_hotplug(smschar_hotplug);
}
EXPORT_SYMBOL(smschar_initialize);

void smschar_terminate(void)
{
	dev_t devno = MKDEV ( smschar_major, smschar_minor );

	unregister_chrdev_region(devno, SMSCHAR_NR_DEVS);
	smscore_unregister_hotplug(smschar_hotplug);
}
EXPORT_SYMBOL(smschar_terminate);

drivers/media/mdtv/smschar.h

deleted100644 → 0
+0 −7
Original line number Diff line number Diff line
#ifndef __smschar_h__
#define __smschar_h__

extern int smschar_initialize(void);
extern void smschar_terminate(void);

#endif // __smschar_h__

drivers/media/mdtv/smscharioctl.h

deleted100644 → 0
+0 −17
Original line number Diff line number Diff line
#ifndef __smscharioctl_h__
#define __smscharioctl_h__

#include <linux/ioctl.h>

typedef struct _smschar_buffer_t
{
	unsigned long offset;		// offset in common buffer (mapped to user space)
	int size;
} smschar_buffer_t;

#define SMSCHAR_SET_DEVICE_MODE	_IOW('K', 0, int)
#define SMSCHAR_GET_DEVICE_MODE	_IOR('K', 1, int)
#define SMSCHAR_GET_BUFFER_SIZE	_IOR('K', 2, int)
#define SMSCHAR_WAIT_GET_BUFFER	_IOR('K', 3, smschar_buffer_t)

#endif // __smscharioctl_h__
+1 −7
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@
#include "smscoreapi.h"
#include "smstypes.h"

#include "smschar.h"

typedef struct _smscore_device_notifyee
{
	struct list_head entry;
@@ -1100,7 +1098,7 @@ int smscore_map_common_buffer(smscore_device_t *coredev, struct vm_area_struct *

int smscore_module_init(void)
{
	int rc;
	int rc = 0;

	INIT_LIST_HEAD(&g_smscore_notifyees);
	INIT_LIST_HEAD(&g_smscore_devices);
@@ -1109,8 +1107,6 @@ int smscore_module_init(void)
	INIT_LIST_HEAD(&g_smscore_registry);
	kmutex_init(&g_smscore_registrylock);

	rc = smschar_initialize();

	printk(KERN_INFO "%s, rc %d\n", __FUNCTION__, rc);

	return rc;
@@ -1118,8 +1114,6 @@ int smscore_module_init(void)

void smscore_module_exit(void)
{
	smschar_terminate();

	kmutex_lock(&g_smscore_deviceslock);
	while (!list_empty(&g_smscore_notifyees))
	{