2008-05-23 05:05:26 +08:00
|
|
|
/*
|
2008-05-23 05:29:20 +08:00
|
|
|
* Siano core API module
|
|
|
|
*
|
|
|
|
* This file contains implementation for the interface to sms core component
|
|
|
|
*
|
V4L/DVB (10750): import changes from Siano
Import the following changes from Uri Shkolnik
* Two-ways merge with Siano internal repository
* Continuing with DVB sub-system separation
* kconfig and makefile updates
* Code cleanup
This is a work-in-progress sync with Siano's internal repository.
Some changes had to be altered or dropped in order not to break the build.
This breaks normal operation for the current driver, but it is being committed
now for tracking purposes.
These changes introduce the following checkpatch.pl violations:
ERROR: do not use C99 // comments
156: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1373:
+//#ifdef DVB_CORE
ERROR: do not use C99 // comments
157: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1374:
+// smsdvb_unregister();
ERROR: do not use C99 // comments
158: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1375:
+//#endif
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
163: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1380:
+EXPORT_SYMBOL(smscore_onresponse);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
164: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1381:
+EXPORT_SYMBOL(sms_get_board);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
165: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1382:
+EXPORT_SYMBOL(sms_debug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
166: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1383:
+EXPORT_SYMBOL(smscore_putbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
167: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1384:
+EXPORT_SYMBOL(smscore_registry_getmode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
168: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1385:
+EXPORT_SYMBOL(smscore_register_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
169: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1386:
+EXPORT_SYMBOL(smscore_set_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
170: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1387:
+EXPORT_SYMBOL(smscore_start_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
171: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1388:
+EXPORT_SYMBOL(smsusb_id_table);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
172: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1389:
+EXPORT_SYMBOL(smscore_unregister_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
173: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1390:
+EXPORT_SYMBOL(smscore_getbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
174: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1391:
+EXPORT_SYMBOL(smscore_get_device_mode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
175: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1392:
+EXPORT_SYMBOL(smscore_register_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
176: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1393:
+EXPORT_SYMBOL(smscore_unregister_hotplug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
177: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1394:
+EXPORT_SYMBOL(smsclient_sendrequest);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
178: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1395:
+EXPORT_SYMBOL(smscore_unregister_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
179: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1396:
+EXPORT_SYMBOL(smscore_get_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
180: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1397:
+EXPORT_SYMBOL(smscore_register_hotplug);
WARNING: line over 80 characters
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
ERROR: "foo* bar" should be "foo *bar"
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
WARNING: line over 80 characters
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: "foo* bar" should be "foo *bar"
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: space required after that ',' (ctx:VxV)
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
489: FILE: linux/drivers/media/dvb/siano/smsusb.c:443:
+ printk(KERN_INFO"%s Entering status %d.\n", __FUNCTION__, msg.event);
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
501: FILE: linux/drivers/media/dvb/siano/smsusb.c:455:
+ printk(KERN_INFO "%s Entering.\n", __FUNCTION__);
ERROR: space prohibited before that '++' (ctx:WxB)
505: FILE: linux/drivers/media/dvb/siano/smsusb.c:459:
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i ++)
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
517: FILE: linux/drivers/media/dvb/siano/smsusb.c:471:
+ __FUNCTION__, rc);
total: 7 errors, 23 warnings, 524 lines checked
Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2008-08-31 11:44:04 +08:00
|
|
|
* author: Uri Shkolnik
|
2008-05-23 05:05:26 +08:00
|
|
|
*
|
2008-05-23 05:29:20 +08:00
|
|
|
* Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
|
2008-05-23 05:05:26 +08:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
2008-09-04 03:48:17 +08:00
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
2008-05-23 05:29:20 +08:00
|
|
|
* published by the Free Software Foundation;
|
2008-05-23 05:05:26 +08:00
|
|
|
*
|
2008-05-23 05:29:20 +08:00
|
|
|
* Software distributed under the License is distributed on an "AS IS"
|
|
|
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
2008-05-23 05:05:26 +08:00
|
|
|
*
|
2008-05-23 05:29:20 +08:00
|
|
|
* See the GNU General Public License for more details.
|
2008-05-23 05:05:26 +08:00
|
|
|
*
|
|
|
|
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/moduleparam.h>
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <linux/delay.h>
|
2008-07-12 11:37:08 +08:00
|
|
|
#include <linux/io.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
#include <linux/firmware.h>
|
2009-05-17 16:59:37 +08:00
|
|
|
#include <linux/wait.h>
|
2009-05-17 17:01:03 +08:00
|
|
|
#include <asm/byteorder.h>
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
#include "smscoreapi.h"
|
2008-06-26 15:58:30 +08:00
|
|
|
#include "sms-cards.h"
|
2009-05-15 03:29:35 +08:00
|
|
|
#include "smsir.h"
|
|
|
|
#include "smsendian.h"
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2009-02-27 13:42:16 +08:00
|
|
|
static int sms_dbg;
|
V4L/DVB (10751): sms1xxx: fix checkpatch.pl violations introduced by previous changeset
Fix checkpatch.pl violations introduced by previous changeset:
ERROR: do not use C99 // comments
156: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1373:
+//#ifdef DVB_CORE
ERROR: do not use C99 // comments
157: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1374:
+// smsdvb_unregister();
ERROR: do not use C99 // comments
158: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1375:
+//#endif
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
163: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1380:
+EXPORT_SYMBOL(smscore_onresponse);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
164: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1381:
+EXPORT_SYMBOL(sms_get_board);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
165: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1382:
+EXPORT_SYMBOL(sms_debug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
166: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1383:
+EXPORT_SYMBOL(smscore_putbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
167: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1384:
+EXPORT_SYMBOL(smscore_registry_getmode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
168: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1385:
+EXPORT_SYMBOL(smscore_register_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
169: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1386:
+EXPORT_SYMBOL(smscore_set_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
170: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1387:
+EXPORT_SYMBOL(smscore_start_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
171: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1388:
+EXPORT_SYMBOL(smsusb_id_table);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
172: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1389:
+EXPORT_SYMBOL(smscore_unregister_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
173: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1390:
+EXPORT_SYMBOL(smscore_getbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
174: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1391:
+EXPORT_SYMBOL(smscore_get_device_mode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
175: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1392:
+EXPORT_SYMBOL(smscore_register_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
176: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1393:
+EXPORT_SYMBOL(smscore_unregister_hotplug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
177: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1394:
+EXPORT_SYMBOL(smsclient_sendrequest);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
178: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1395:
+EXPORT_SYMBOL(smscore_unregister_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
179: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1396:
+EXPORT_SYMBOL(smscore_get_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
180: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1397:
+EXPORT_SYMBOL(smscore_register_hotplug);
WARNING: line over 80 characters
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
ERROR: "foo* bar" should be "foo *bar"
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
WARNING: line over 80 characters
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: "foo* bar" should be "foo *bar"
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: space required after that ',' (ctx:VxV)
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
489: FILE: linux/drivers/media/dvb/siano/smsusb.c:443:
+ printk(KERN_INFO"%s Entering status %d.\n", __FUNCTION__, msg.event);
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
501: FILE: linux/drivers/media/dvb/siano/smsusb.c:455:
+ printk(KERN_INFO "%s Entering.\n", __FUNCTION__);
ERROR: space prohibited before that '++' (ctx:WxB)
505: FILE: linux/drivers/media/dvb/siano/smsusb.c:459:
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i ++)
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
517: FILE: linux/drivers/media/dvb/siano/smsusb.c:471:
+ __FUNCTION__, rc);
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
[mchehab@redhat.com: sms_dbg were declared on 3 different files]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2008-09-01 03:08:15 +08:00
|
|
|
module_param_named(debug, sms_dbg, int, 0644);
|
2008-06-20 07:59:08 +08:00
|
|
|
MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
|
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_notifyee_t {
|
2008-05-20 05:56:13 +08:00
|
|
|
struct list_head entry;
|
|
|
|
hotplug_t hotplug;
|
2008-06-16 04:52:24 +08:00
|
|
|
};
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_idlist_t {
|
2008-06-14 11:43:26 +08:00
|
|
|
struct list_head entry;
|
|
|
|
int id;
|
|
|
|
int data_type;
|
2008-06-16 04:52:24 +08:00
|
|
|
};
|
2008-06-14 11:43:26 +08:00
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_client_t {
|
2008-05-20 05:56:13 +08:00
|
|
|
struct list_head entry;
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_t *coredev;
|
2008-05-20 05:56:13 +08:00
|
|
|
void *context;
|
2008-06-14 11:43:26 +08:00
|
|
|
struct list_head idlist;
|
2008-05-20 05:56:13 +08:00
|
|
|
onresponse_t onresponse_handler;
|
|
|
|
onremove_t onremove_handler;
|
2008-06-16 04:52:24 +08:00
|
|
|
};
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-19 09:09:55 +08:00
|
|
|
void smscore_set_board_id(struct smscore_device_t *core, int id)
|
|
|
|
{
|
|
|
|
core->board_id = id;
|
|
|
|
}
|
|
|
|
|
2008-11-23 02:32:19 +08:00
|
|
|
int smscore_led_state(struct smscore_device_t *core, int led)
|
|
|
|
{
|
|
|
|
if (led >= 0)
|
|
|
|
core->led_state = led;
|
|
|
|
return core->led_state;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_set_board_id);
|
2008-11-23 02:32:19 +08:00
|
|
|
|
2008-06-19 09:09:55 +08:00
|
|
|
int smscore_get_board_id(struct smscore_device_t *core)
|
|
|
|
{
|
|
|
|
return core->board_id;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_get_board_id);
|
2008-06-19 09:09:55 +08:00
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t {
|
2008-05-20 05:56:13 +08:00
|
|
|
struct list_head entry;
|
|
|
|
char devpath[32];
|
|
|
|
int mode;
|
2008-06-16 04:52:24 +08:00
|
|
|
enum sms_device_type_st type;
|
|
|
|
};
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-07-22 10:17:36 +08:00
|
|
|
static struct list_head g_smscore_notifyees;
|
|
|
|
static struct list_head g_smscore_devices;
|
|
|
|
static struct mutex g_smscore_deviceslock;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-07-22 10:17:36 +08:00
|
|
|
static struct list_head g_smscore_registry;
|
|
|
|
static struct mutex g_smscore_registrylock;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-19 07:25:25 +08:00
|
|
|
static int default_mode = 4;
|
2008-06-14 11:43:26 +08:00
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
module_param(default_mode, int, 0644);
|
|
|
|
MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
|
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t *entry;
|
2008-05-20 05:56:13 +08:00
|
|
|
struct list_head *next;
|
|
|
|
|
|
|
|
kmutex_lock(&g_smscore_registrylock);
|
2008-06-16 02:14:13 +08:00
|
|
|
for (next = g_smscore_registry.next;
|
|
|
|
next != &g_smscore_registry;
|
|
|
|
next = next->next) {
|
2008-06-16 04:52:24 +08:00
|
|
|
entry = (struct smscore_registry_entry_t *) next;
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!strcmp(entry->devpath, devpath)) {
|
2008-05-20 05:56:13 +08:00
|
|
|
kmutex_unlock(&g_smscore_registrylock);
|
2008-06-14 11:43:26 +08:00
|
|
|
return entry;
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-29 12:29:29 +08:00
|
|
|
entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (entry) {
|
2008-05-20 05:56:13 +08:00
|
|
|
entry->mode = default_mode;
|
|
|
|
strcpy(entry->devpath, devpath);
|
|
|
|
list_add(&entry->entry, &g_smscore_registry);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("failed to create smscore_registry.");
|
2008-05-20 05:56:13 +08:00
|
|
|
kmutex_unlock(&g_smscore_registrylock);
|
2008-06-14 11:43:26 +08:00
|
|
|
return entry;
|
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
int smscore_registry_getmode(char *devpath)
|
2008-06-14 11:43:26 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t *entry;
|
2008-06-14 11:43:26 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
entry = smscore_find_registry(devpath);
|
|
|
|
if (entry)
|
2008-06-14 11:43:26 +08:00
|
|
|
return entry->mode;
|
|
|
|
else
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("No registry found.");
|
2008-06-16 02:14:13 +08:00
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
return default_mode;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_registry_getmode);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static enum sms_device_type_st smscore_registry_gettype(char *devpath)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t *entry;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
entry = smscore_find_registry(devpath);
|
|
|
|
if (entry)
|
2008-06-14 11:43:26 +08:00
|
|
|
return entry->type;
|
|
|
|
else
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("No registry found.");
|
2008-06-16 02:14:13 +08:00
|
|
|
|
2008-06-14 11:43:26 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
void smscore_registry_setmode(char *devpath, int mode)
|
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t *entry;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
entry = smscore_find_registry(devpath);
|
|
|
|
if (entry)
|
|
|
|
entry->mode = mode;
|
2008-06-14 11:43:26 +08:00
|
|
|
else
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("No registry found.");
|
2008-06-16 02:14:13 +08:00
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static void smscore_registry_settype(char *devpath,
|
|
|
|
enum sms_device_type_st type)
|
2008-06-14 11:43:26 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t *entry;
|
2008-06-14 11:43:26 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
entry = smscore_find_registry(devpath);
|
|
|
|
if (entry)
|
2008-06-14 11:43:26 +08:00
|
|
|
entry->type = type;
|
|
|
|
else
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("No registry found.");
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static void list_add_locked(struct list_head *new, struct list_head *head,
|
|
|
|
spinlock_t *lock)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(lock, flags);
|
|
|
|
|
|
|
|
list_add(new, head);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(lock, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* register a client callback that called when device plugged in/unplugged
|
|
|
|
* NOTE: if devices exist callback is called immediately for each device
|
|
|
|
*
|
|
|
|
* @param hotplug callback
|
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
|
|
|
int smscore_register_hotplug(hotplug_t hotplug)
|
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_notifyee_t *notifyee;
|
2008-05-20 05:56:13 +08:00
|
|
|
struct list_head *next, *first;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
kmutex_lock(&g_smscore_deviceslock);
|
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
|
|
|
|
GFP_KERNEL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (notifyee) {
|
|
|
|
/* now notify callback about existing devices */
|
2008-05-20 05:56:13 +08:00
|
|
|
first = &g_smscore_devices;
|
2008-06-16 02:14:13 +08:00
|
|
|
for (next = first->next;
|
|
|
|
next != first && !rc;
|
|
|
|
next = next->next) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_t *coredev =
|
|
|
|
(struct smscore_device_t *) next;
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = hotplug(coredev, coredev->device, 1);
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc >= 0) {
|
2008-05-20 05:56:13 +08:00
|
|
|
notifyee->hotplug = hotplug;
|
|
|
|
list_add(¬ifyee->entry, &g_smscore_notifyees);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else
|
2008-05-20 05:56:13 +08:00
|
|
|
kfree(notifyee);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = -ENOMEM;
|
|
|
|
|
|
|
|
kmutex_unlock(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_register_hotplug);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* unregister a client callback that called when device plugged in/unplugged
|
|
|
|
*
|
|
|
|
* @param hotplug callback
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void smscore_unregister_hotplug(hotplug_t hotplug)
|
|
|
|
{
|
|
|
|
struct list_head *next, *first;
|
|
|
|
|
|
|
|
kmutex_lock(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
first = &g_smscore_notifyees;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
for (next = first->next; next != first;) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_notifyee_t *notifyee =
|
|
|
|
(struct smscore_device_notifyee_t *) next;
|
2008-05-20 05:56:13 +08:00
|
|
|
next = next->next;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (notifyee->hotplug == hotplug) {
|
2008-05-20 05:56:13 +08:00
|
|
|
list_del(¬ifyee->entry);
|
|
|
|
kfree(notifyee);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kmutex_unlock(&g_smscore_deviceslock);
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_unregister_hotplug);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static void smscore_notify_clients(struct smscore_device_t *coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_client_t *client;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* the client must call smscore_unregister_client from remove handler */
|
|
|
|
while (!list_empty(&coredev->clients)) {
|
2008-06-16 04:52:24 +08:00
|
|
|
client = (struct smscore_client_t *) coredev->clients.next;
|
2008-05-20 05:56:13 +08:00
|
|
|
client->onremove_handler(client->context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static int smscore_notify_callbacks(struct smscore_device_t *coredev,
|
|
|
|
struct device *device, int arrival)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
|
|
|
struct list_head *next, *first;
|
|
|
|
int rc = 0;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* note: must be called under g_deviceslock */
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
first = &g_smscore_notifyees;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
for (next = first->next; next != first; next = next->next) {
|
2008-06-16 04:52:24 +08:00
|
|
|
rc = ((struct smscore_device_notifyee_t *) next)->
|
2008-06-16 03:50:11 +08:00
|
|
|
hotplug(coredev, device, arrival);
|
2008-05-20 05:56:13 +08:00
|
|
|
if (rc < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static struct
|
|
|
|
smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
|
2008-05-06 14:11:51 +08:00
|
|
|
dma_addr_t common_buffer_phys)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_buffer_t *cb =
|
|
|
|
kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!cb) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("kmalloc(...) failed");
|
2008-05-20 05:56:13 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->p = buffer;
|
2008-06-14 18:40:41 +08:00
|
|
|
cb->offset_in_common = buffer - (u8 *) common_buffer;
|
2008-05-20 05:56:13 +08:00
|
|
|
cb->phys = common_buffer_phys + cb->offset_in_common;
|
|
|
|
|
|
|
|
return cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-06-16 02:14:13 +08:00
|
|
|
* creates coredev object for a device, prepares buffers,
|
|
|
|
* creates buffer mappings, notifies registered hotplugs about new device.
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param params device pointer to struct with device specific parameters
|
|
|
|
* and handlers
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param coredev pointer to a value that receives created coredev object
|
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
int smscore_register_device(struct smsdevice_params_t *params,
|
|
|
|
struct smscore_device_t **coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_t *dev;
|
2008-05-20 05:56:13 +08:00
|
|
|
u8 *buffer;
|
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!dev) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("kzalloc(...) failed");
|
2008-05-20 05:56:13 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* init list entry so it could be safe in smscore_unregister_device */
|
2008-05-20 05:56:13 +08:00
|
|
|
INIT_LIST_HEAD(&dev->entry);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* init queues */
|
2008-05-20 05:56:13 +08:00
|
|
|
INIT_LIST_HEAD(&dev->clients);
|
|
|
|
INIT_LIST_HEAD(&dev->buffers);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* init locks */
|
2008-05-20 05:56:13 +08:00
|
|
|
spin_lock_init(&dev->clientslock);
|
|
|
|
spin_lock_init(&dev->bufferslock);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* init completion events */
|
2008-05-20 05:56:13 +08:00
|
|
|
init_completion(&dev->version_ex_done);
|
|
|
|
init_completion(&dev->data_download_done);
|
|
|
|
init_completion(&dev->trigger_done);
|
|
|
|
init_completion(&dev->init_device_done);
|
|
|
|
init_completion(&dev->reload_start_done);
|
|
|
|
init_completion(&dev->resume_done);
|
2009-05-19 23:52:58 +08:00
|
|
|
init_completion(&dev->gpio_configuration_done);
|
|
|
|
init_completion(&dev->gpio_set_level_done);
|
|
|
|
init_completion(&dev->gpio_get_level_done);
|
2009-05-15 03:29:35 +08:00
|
|
|
init_completion(&dev->ir_init_done);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2009-05-17 16:59:37 +08:00
|
|
|
/* Buffer management */
|
|
|
|
init_waitqueue_head(&dev->buffer_mng_waitq);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* alloc common buffer */
|
2008-05-20 05:56:13 +08:00
|
|
|
dev->common_buffer_size = params->buffer_size * params->num_buffers;
|
2008-06-16 02:14:13 +08:00
|
|
|
dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
|
|
|
|
&dev->common_buffer_phys,
|
|
|
|
GFP_KERNEL | GFP_DMA);
|
|
|
|
if (!dev->common_buffer) {
|
2008-05-20 05:56:13 +08:00
|
|
|
smscore_unregister_device(dev);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* prepare dma buffers */
|
|
|
|
for (buffer = dev->common_buffer;
|
|
|
|
dev->num_buffers < params->num_buffers;
|
2008-06-16 02:52:43 +08:00
|
|
|
dev->num_buffers++, buffer += params->buffer_size) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_buffer_t *cb =
|
2008-06-16 03:50:11 +08:00
|
|
|
smscore_createbuffer(buffer, dev->common_buffer,
|
|
|
|
dev->common_buffer_phys);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!cb) {
|
2008-05-20 05:56:13 +08:00
|
|
|
smscore_unregister_device(dev);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
smscore_putbuffer(dev, cb);
|
|
|
|
}
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("allocated %d buffers", dev->num_buffers);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
dev->mode = DEVICE_MODE_NONE;
|
|
|
|
dev->context = params->context;
|
|
|
|
dev->device = params->device;
|
|
|
|
dev->setmode_handler = params->setmode_handler;
|
|
|
|
dev->detectmode_handler = params->detectmode_handler;
|
|
|
|
dev->sendrequest_handler = params->sendrequest_handler;
|
|
|
|
dev->preload_handler = params->preload_handler;
|
|
|
|
dev->postload_handler = params->postload_handler;
|
|
|
|
|
|
|
|
dev->device_flags = params->flags;
|
|
|
|
strcpy(dev->devpath, params->devpath);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
smscore_registry_settype(dev->devpath, params->device_type);
|
2008-06-14 11:43:26 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* add device to devices list */
|
2008-05-20 05:56:13 +08:00
|
|
|
kmutex_lock(&g_smscore_deviceslock);
|
|
|
|
list_add(&dev->entry, &g_smscore_devices);
|
|
|
|
kmutex_unlock(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
*coredev = dev;
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("device %p created", dev);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_register_device);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2009-05-15 03:29:35 +08:00
|
|
|
|
|
|
|
static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
|
|
|
|
void *buffer, size_t size, struct completion *completion) {
|
|
|
|
int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
|
|
|
|
if (rc < 0) {
|
|
|
|
sms_info("sendrequest returned error %d", rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return wait_for_completion_timeout(completion,
|
|
|
|
msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ?
|
|
|
|
0 : -ETIME;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts & enables IR operations
|
|
|
|
*
|
|
|
|
* @return 0 on success, < 0 on error.
|
|
|
|
*/
|
|
|
|
static int smscore_init_ir(struct smscore_device_t *coredev)
|
|
|
|
{
|
|
|
|
int ir_io;
|
|
|
|
int rc;
|
|
|
|
void *buffer;
|
|
|
|
|
2010-10-30 03:08:23 +08:00
|
|
|
coredev->ir.dev = NULL;
|
2009-05-15 03:29:35 +08:00
|
|
|
ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
|
|
|
|
if (ir_io) {/* only if IR port exist we use IR sub-module */
|
|
|
|
sms_info("IR loading");
|
|
|
|
rc = sms_ir_init(coredev);
|
|
|
|
|
|
|
|
if (rc != 0)
|
|
|
|
sms_err("Error initialization DTV IR sub-module");
|
|
|
|
else {
|
|
|
|
buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
|
|
|
|
SMS_DMA_ALIGNMENT,
|
|
|
|
GFP_KERNEL | GFP_DMA);
|
|
|
|
if (buffer) {
|
|
|
|
struct SmsMsgData_ST2 *msg =
|
|
|
|
(struct SmsMsgData_ST2 *)
|
|
|
|
SMS_ALIGN_ADDRESS(buffer);
|
|
|
|
|
|
|
|
SMS_INIT_MSG(&msg->xMsgHeader,
|
|
|
|
MSG_SMS_START_IR_REQ,
|
|
|
|
sizeof(struct SmsMsgData_ST2));
|
|
|
|
msg->msgData[0] = coredev->ir.controller;
|
|
|
|
msg->msgData[1] = coredev->ir.timeout;
|
|
|
|
|
|
|
|
smsendian_handle_tx_message(
|
|
|
|
(struct SmsMsgHdr_ST2 *)msg);
|
|
|
|
rc = smscore_sendrequest_and_wait(coredev, msg,
|
|
|
|
msg->xMsgHeader. msgLength,
|
|
|
|
&coredev->ir_init_done);
|
|
|
|
|
|
|
|
kfree(buffer);
|
|
|
|
} else
|
|
|
|
sms_err
|
|
|
|
("Sending IR initialization message failed");
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
sms_info("IR port has not been detected");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
/**
|
|
|
|
* sets initial device mode and notifies client hotplugs that device is ready
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
int smscore_start_device(struct smscore_device_t *coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 03:50:11 +08:00
|
|
|
int rc = smscore_set_device_mode(
|
|
|
|
coredev, smscore_registry_getmode(coredev->devpath));
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc < 0) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("set device mode faile , rc %d", rc);
|
2008-05-20 05:56:13 +08:00
|
|
|
return rc;
|
2008-06-14 11:43:26 +08:00
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
kmutex_lock(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
rc = smscore_notify_callbacks(coredev, coredev->device, 1);
|
2009-05-15 03:29:35 +08:00
|
|
|
smscore_init_ir(coredev);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("device %p started, rc %d", coredev, rc);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
kmutex_unlock(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_start_device);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
|
|
|
|
void *buffer, size_t size)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
|
|
|
|
struct SmsMsgHdr_ST *msg;
|
2009-05-17 17:01:03 +08:00
|
|
|
u32 mem_address;
|
2008-05-06 14:11:51 +08:00
|
|
|
u8 *payload = firmware->Payload;
|
2008-05-20 05:56:13 +08:00
|
|
|
int rc = 0;
|
2009-05-17 17:01:03 +08:00
|
|
|
firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
|
|
|
|
firmware->Length = le32_to_cpu(firmware->Length);
|
|
|
|
|
|
|
|
mem_address = firmware->StartAddress;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("loading FW to addr 0x%x size %d",
|
|
|
|
mem_address, firmware->Length);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (coredev->preload_handler) {
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = coredev->preload_handler(coredev->context);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* PAGE_SIZE buffer shall be enough and dma aligned */
|
2008-06-16 06:11:37 +08:00
|
|
|
msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
|
2008-05-20 05:56:13 +08:00
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (coredev->mode != DEVICE_MODE_NONE) {
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_debug("sending reload command.");
|
2008-06-16 02:14:13 +08:00
|
|
|
SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
|
2008-06-16 04:52:24 +08:00
|
|
|
sizeof(struct SmsMsgHdr_ST));
|
2008-06-16 02:14:13 +08:00
|
|
|
rc = smscore_sendrequest_and_wait(coredev, msg,
|
|
|
|
msg->msgLength,
|
|
|
|
&coredev->reload_start_done);
|
2008-06-16 02:32:00 +08:00
|
|
|
mem_address = *(u32 *) &payload[20];
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
|
2008-06-16 02:52:43 +08:00
|
|
|
while (size && rc >= 0) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct SmsDataDownload_ST *DataMsg =
|
|
|
|
(struct SmsDataDownload_ST *) msg;
|
2008-05-20 05:56:13 +08:00
|
|
|
int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
|
2008-06-16 04:52:24 +08:00
|
|
|
(u16)(sizeof(struct SmsMsgHdr_ST) +
|
2008-06-16 02:32:00 +08:00
|
|
|
sizeof(u32) + payload_size));
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
DataMsg->MemAddr = mem_address;
|
|
|
|
memcpy(DataMsg->Payload, payload, payload_size);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
|
|
|
|
(coredev->mode == DEVICE_MODE_NONE))
|
2008-06-16 03:50:11 +08:00
|
|
|
rc = coredev->sendrequest_handler(
|
|
|
|
coredev->context, DataMsg,
|
|
|
|
DataMsg->xMsgHeader.msgLength);
|
2008-05-20 05:56:13 +08:00
|
|
|
else
|
2008-06-16 03:50:11 +08:00
|
|
|
rc = smscore_sendrequest_and_wait(
|
|
|
|
coredev, DataMsg,
|
|
|
|
DataMsg->xMsgHeader.msgLength,
|
|
|
|
&coredev->data_download_done);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
payload += payload_size;
|
|
|
|
size -= payload_size;
|
|
|
|
mem_address += payload_size;
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc >= 0) {
|
|
|
|
if (coredev->mode == DEVICE_MODE_NONE) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct SmsMsgData_ST *TriggerMsg =
|
|
|
|
(struct SmsMsgData_ST *) msg;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
|
2008-06-16 04:52:24 +08:00
|
|
|
sizeof(struct SmsMsgHdr_ST) +
|
2008-06-16 02:32:00 +08:00
|
|
|
sizeof(u32) * 5);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 03:50:11 +08:00
|
|
|
TriggerMsg->msgData[0] = firmware->StartAddress;
|
|
|
|
/* Entry point */
|
2008-06-16 02:52:43 +08:00
|
|
|
TriggerMsg->msgData[1] = 5; /* Priority */
|
|
|
|
TriggerMsg->msgData[2] = 0x200; /* Stack size */
|
|
|
|
TriggerMsg->msgData[3] = 0; /* Parameter */
|
|
|
|
TriggerMsg->msgData[4] = 4; /* Task ID */
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
|
2008-06-16 03:50:11 +08:00
|
|
|
rc = coredev->sendrequest_handler(
|
|
|
|
coredev->context, TriggerMsg,
|
|
|
|
TriggerMsg->xMsgHeader.msgLength);
|
2008-05-20 05:56:13 +08:00
|
|
|
msleep(100);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else
|
2008-06-16 03:50:11 +08:00
|
|
|
rc = smscore_sendrequest_and_wait(
|
|
|
|
coredev, TriggerMsg,
|
|
|
|
TriggerMsg->xMsgHeader.msgLength,
|
|
|
|
&coredev->trigger_done);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else {
|
|
|
|
SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
|
2008-06-16 04:52:24 +08:00
|
|
|
sizeof(struct SmsMsgHdr_ST));
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
rc = coredev->sendrequest_handler(coredev->context,
|
|
|
|
msg, msg->msgLength);
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
2008-06-16 02:14:13 +08:00
|
|
|
msleep(500);
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("rc=%d, postload=%p ", rc,
|
2008-06-19 12:15:46 +08:00
|
|
|
coredev->postload_handler);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
kfree(msg);
|
|
|
|
|
2008-06-14 11:43:26 +08:00
|
|
|
return ((rc >= 0) && coredev->postload_handler) ?
|
2008-05-20 05:56:13 +08:00
|
|
|
coredev->postload_handler(coredev->context) :
|
|
|
|
rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* loads specified firmware into a buffer and calls device loadfirmware_handler
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param filename null-terminated string specifies firmware file name
|
|
|
|
* @param loadfirmware_handler device handler that loads firmware
|
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-21 13:44:02 +08:00
|
|
|
static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
|
|
|
|
char *filename,
|
|
|
|
loadfirmware_t loadfirmware_handler)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
|
|
|
int rc = -ENOENT;
|
|
|
|
const struct firmware *fw;
|
2008-05-06 14:11:51 +08:00
|
|
|
u8 *fw_buffer;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (loadfirmware_handler == NULL && !(coredev->device_flags &
|
|
|
|
SMS_DEVICE_FAMILY2))
|
2008-05-20 05:56:13 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
rc = request_firmware(&fw, filename, coredev->device);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc < 0) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("failed to open \"%s\"", filename);
|
2008-05-20 05:56:13 +08:00
|
|
|
return rc;
|
|
|
|
}
|
2008-06-29 07:53:45 +08:00
|
|
|
sms_info("read FW %s, size=%zd", filename, fw->size);
|
2008-06-16 02:14:13 +08:00
|
|
|
fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
|
|
|
|
GFP_KERNEL | GFP_DMA);
|
|
|
|
if (fw_buffer) {
|
2008-05-20 05:56:13 +08:00
|
|
|
memcpy(fw_buffer, fw->data, fw->size);
|
|
|
|
|
|
|
|
rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
|
2008-06-16 03:50:11 +08:00
|
|
|
smscore_load_firmware_family2(coredev,
|
|
|
|
fw_buffer,
|
|
|
|
fw->size) :
|
|
|
|
loadfirmware_handler(coredev->context,
|
|
|
|
fw_buffer, fw->size);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
kfree(fw_buffer);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("failed to allocate firmware buffer");
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
release_firmware(fw);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-06-16 03:50:11 +08:00
|
|
|
* notifies all clients registered with the device, notifies hotplugs,
|
|
|
|
* frees all buffers and coredev object
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
void smscore_unregister_device(struct smscore_device_t *coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_buffer_t *cb;
|
2008-05-20 05:56:13 +08:00
|
|
|
int num_buffers = 0;
|
2008-06-14 11:43:26 +08:00
|
|
|
int retry = 0;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
kmutex_lock(&g_smscore_deviceslock);
|
|
|
|
|
2009-05-15 03:29:35 +08:00
|
|
|
/* Release input device (IR) resources */
|
|
|
|
sms_ir_exit(coredev);
|
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
smscore_notify_clients(coredev);
|
|
|
|
smscore_notify_callbacks(coredev, NULL, 0);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* at this point all buffers should be back
|
|
|
|
* onresponse must no longer be called */
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
while (1) {
|
2009-05-17 16:59:37 +08:00
|
|
|
while (!list_empty(&coredev->buffers)) {
|
|
|
|
cb = (struct smscore_buffer_t *) coredev->buffers.next;
|
|
|
|
list_del(&cb->entry);
|
2008-05-20 05:56:13 +08:00
|
|
|
kfree(cb);
|
2008-06-16 02:52:43 +08:00
|
|
|
num_buffers++;
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
if (num_buffers == coredev->num_buffers)
|
|
|
|
break;
|
2008-06-16 02:14:13 +08:00
|
|
|
if (++retry > 10) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("exiting although "
|
|
|
|
"not all buffers released.");
|
2008-06-14 11:43:26 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("waiting for %d buffer(s)",
|
2008-06-19 12:15:46 +08:00
|
|
|
coredev->num_buffers - num_buffers);
|
2008-05-20 05:56:13 +08:00
|
|
|
msleep(100);
|
|
|
|
}
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("freed %d buffers", num_buffers);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
if (coredev->common_buffer)
|
2008-06-16 02:14:13 +08:00
|
|
|
dma_free_coherent(NULL, coredev->common_buffer_size,
|
2009-05-17 16:59:37 +08:00
|
|
|
coredev->common_buffer, coredev->common_buffer_phys);
|
|
|
|
|
|
|
|
if (coredev->fw_buf != NULL)
|
|
|
|
kfree(coredev->fw_buf);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
list_del(&coredev->entry);
|
|
|
|
kfree(coredev);
|
|
|
|
|
|
|
|
kmutex_unlock(&g_smscore_deviceslock);
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("device %p destroyed", coredev);
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_unregister_device);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static int smscore_detect_mode(struct smscore_device_t *coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
|
2008-06-16 02:14:13 +08:00
|
|
|
GFP_KERNEL | GFP_DMA);
|
2008-06-16 04:52:24 +08:00
|
|
|
struct SmsMsgHdr_ST *msg =
|
|
|
|
(struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
|
2008-05-20 05:56:13 +08:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (!buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
|
|
|
|
sizeof(struct SmsMsgHdr_ST));
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
|
|
|
|
&coredev->version_ex_done);
|
|
|
|
if (rc == -ETIME) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (wait_for_completion_timeout(&coredev->resume_done,
|
|
|
|
msecs_to_jiffies(5000))) {
|
2008-06-16 03:50:11 +08:00
|
|
|
rc = smscore_sendrequest_and_wait(
|
|
|
|
coredev, msg, msg->msgLength,
|
|
|
|
&coredev->version_ex_done);
|
2008-05-20 05:56:13 +08:00
|
|
|
if (rc < 0)
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
|
|
|
|
"second try, rc %d", rc);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = -ETIME;
|
|
|
|
}
|
|
|
|
|
|
|
|
kfree(buffer);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
|
2008-06-16 06:27:35 +08:00
|
|
|
/*Stellar NOVA A0 Nova B0 VEGA*/
|
|
|
|
/*DVBT*/
|
|
|
|
{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
|
|
|
|
/*DVBH*/
|
|
|
|
{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
|
|
|
|
/*TDMB*/
|
V4L/DVB (10750): import changes from Siano
Import the following changes from Uri Shkolnik
* Two-ways merge with Siano internal repository
* Continuing with DVB sub-system separation
* kconfig and makefile updates
* Code cleanup
This is a work-in-progress sync with Siano's internal repository.
Some changes had to be altered or dropped in order not to break the build.
This breaks normal operation for the current driver, but it is being committed
now for tracking purposes.
These changes introduce the following checkpatch.pl violations:
ERROR: do not use C99 // comments
156: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1373:
+//#ifdef DVB_CORE
ERROR: do not use C99 // comments
157: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1374:
+// smsdvb_unregister();
ERROR: do not use C99 // comments
158: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1375:
+//#endif
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
163: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1380:
+EXPORT_SYMBOL(smscore_onresponse);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
164: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1381:
+EXPORT_SYMBOL(sms_get_board);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
165: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1382:
+EXPORT_SYMBOL(sms_debug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
166: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1383:
+EXPORT_SYMBOL(smscore_putbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
167: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1384:
+EXPORT_SYMBOL(smscore_registry_getmode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
168: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1385:
+EXPORT_SYMBOL(smscore_register_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
169: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1386:
+EXPORT_SYMBOL(smscore_set_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
170: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1387:
+EXPORT_SYMBOL(smscore_start_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
171: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1388:
+EXPORT_SYMBOL(smsusb_id_table);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
172: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1389:
+EXPORT_SYMBOL(smscore_unregister_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
173: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1390:
+EXPORT_SYMBOL(smscore_getbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
174: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1391:
+EXPORT_SYMBOL(smscore_get_device_mode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
175: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1392:
+EXPORT_SYMBOL(smscore_register_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
176: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1393:
+EXPORT_SYMBOL(smscore_unregister_hotplug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
177: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1394:
+EXPORT_SYMBOL(smsclient_sendrequest);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
178: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1395:
+EXPORT_SYMBOL(smscore_unregister_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
179: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1396:
+EXPORT_SYMBOL(smscore_get_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
180: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1397:
+EXPORT_SYMBOL(smscore_register_hotplug);
WARNING: line over 80 characters
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
ERROR: "foo* bar" should be "foo *bar"
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
WARNING: line over 80 characters
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: "foo* bar" should be "foo *bar"
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: space required after that ',' (ctx:VxV)
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
489: FILE: linux/drivers/media/dvb/siano/smsusb.c:443:
+ printk(KERN_INFO"%s Entering status %d.\n", __FUNCTION__, msg.event);
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
501: FILE: linux/drivers/media/dvb/siano/smsusb.c:455:
+ printk(KERN_INFO "%s Entering.\n", __FUNCTION__);
ERROR: space prohibited before that '++' (ctx:WxB)
505: FILE: linux/drivers/media/dvb/siano/smsusb.c:459:
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i ++)
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
517: FILE: linux/drivers/media/dvb/siano/smsusb.c:471:
+ __FUNCTION__, rc);
total: 7 errors, 23 warnings, 524 lines checked
Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2008-08-31 11:44:04 +08:00
|
|
|
{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
|
2008-06-16 06:27:35 +08:00
|
|
|
/*DABIP*/
|
|
|
|
{"none", "none", "none", "none"},
|
|
|
|
/*BDA*/
|
|
|
|
{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
|
|
|
|
/*ISDBT*/
|
2009-05-17 17:01:55 +08:00
|
|
|
{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
|
2008-06-16 06:27:35 +08:00
|
|
|
/*ISDBTBDA*/
|
|
|
|
{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
|
|
|
|
/*CMMB*/
|
|
|
|
{"none", "none", "none", "cmmb_vega_12mhz.inp"}
|
2008-05-20 05:56:13 +08:00
|
|
|
};
|
|
|
|
|
2008-06-26 15:58:30 +08:00
|
|
|
static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
|
|
|
|
int mode, enum sms_device_type_st type)
|
|
|
|
{
|
|
|
|
char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
|
|
|
|
return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
|
|
|
|
}
|
2008-06-14 11:43:26 +08:00
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
/**
|
|
|
|
* calls device handler to change mode of operation
|
|
|
|
* NOTE: stellar/usb may disconnect when changing mode
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param mode requested mode of operation
|
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
|
|
|
void *buffer;
|
|
|
|
int rc = 0;
|
2008-06-16 04:52:24 +08:00
|
|
|
enum sms_device_type_st type;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_debug("set device mode to %d", mode);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
|
2009-08-11 09:59:33 +08:00
|
|
|
if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
|
2008-06-20 09:07:23 +08:00
|
|
|
sms_err("invalid mode specified %d", mode);
|
2008-05-20 05:56:13 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2008-06-14 11:43:26 +08:00
|
|
|
smscore_registry_setmode(coredev->devpath, mode);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = smscore_detect_mode(coredev);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc < 0) {
|
2008-06-20 09:07:23 +08:00
|
|
|
sms_err("mode detect failed %d", rc);
|
2008-05-20 05:56:13 +08:00
|
|
|
return rc;
|
2008-06-16 02:14:13 +08:00
|
|
|
}
|
2008-06-14 11:43:26 +08:00
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (coredev->mode == mode) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("device mode %d already set", mode);
|
2008-05-20 05:56:13 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!(coredev->modes_supported & (1 << mode))) {
|
2008-06-26 15:58:30 +08:00
|
|
|
char *fw_filename;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
type = smscore_registry_gettype(coredev->devpath);
|
2008-06-26 15:58:30 +08:00
|
|
|
fw_filename = sms_get_fw_name(coredev, mode, type);
|
|
|
|
|
|
|
|
rc = smscore_load_firmware_from_file(coredev,
|
|
|
|
fw_filename, NULL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc < 0) {
|
2008-06-29 10:27:19 +08:00
|
|
|
sms_warn("error %d loading firmware: %s, "
|
|
|
|
"trying again with default firmware",
|
|
|
|
rc, fw_filename);
|
2008-06-26 15:58:30 +08:00
|
|
|
|
|
|
|
/* try again with the default firmware */
|
2008-06-29 10:27:19 +08:00
|
|
|
fw_filename = smscore_fw_lkup[mode][type];
|
2008-06-26 15:58:30 +08:00
|
|
|
rc = smscore_load_firmware_from_file(coredev,
|
2008-06-29 10:27:19 +08:00
|
|
|
fw_filename, NULL);
|
2008-06-26 15:58:30 +08:00
|
|
|
|
|
|
|
if (rc < 0) {
|
2008-06-29 10:27:19 +08:00
|
|
|
sms_warn("error %d loading "
|
|
|
|
"firmware: %s", rc,
|
|
|
|
fw_filename);
|
2008-06-26 15:58:30 +08:00
|
|
|
return rc;
|
|
|
|
}
|
2008-06-16 02:14:13 +08:00
|
|
|
}
|
2008-06-29 10:27:19 +08:00
|
|
|
sms_log("firmware download success: %s", fw_filename);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("mode %d supported by running "
|
|
|
|
"firmware", mode);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
|
|
|
|
SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (buffer) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct SmsMsgData_ST *msg =
|
|
|
|
(struct SmsMsgData_ST *)
|
|
|
|
SMS_ALIGN_ADDRESS(buffer);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 03:50:11 +08:00
|
|
|
SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
|
2008-06-16 04:52:24 +08:00
|
|
|
sizeof(struct SmsMsgData_ST));
|
2008-05-20 05:56:13 +08:00
|
|
|
msg->msgData[0] = mode;
|
|
|
|
|
2008-06-16 03:50:11 +08:00
|
|
|
rc = smscore_sendrequest_and_wait(
|
|
|
|
coredev, msg, msg->xMsgHeader.msgLength,
|
|
|
|
&coredev->init_device_done);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
kfree(buffer);
|
2008-06-16 02:14:13 +08:00
|
|
|
} else {
|
2008-06-20 09:07:23 +08:00
|
|
|
sms_err("Could not allocate buffer for "
|
|
|
|
"init device message.");
|
2008-05-20 05:56:13 +08:00
|
|
|
rc = -ENOMEM;
|
2008-06-16 02:14:13 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
|
2008-06-20 09:07:23 +08:00
|
|
|
sms_err("invalid mode specified %d", mode);
|
2008-06-14 11:43:26 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
smscore_registry_setmode(coredev->devpath, mode);
|
|
|
|
|
2008-05-20 05:56:13 +08:00
|
|
|
if (coredev->detectmode_handler)
|
2008-06-16 02:14:13 +08:00
|
|
|
coredev->detectmode_handler(coredev->context,
|
|
|
|
&coredev->mode);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
if (coredev->mode != mode && coredev->setmode_handler)
|
|
|
|
rc = coredev->setmode_handler(coredev->context, mode);
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc >= 0) {
|
2008-05-20 05:56:13 +08:00
|
|
|
coredev->mode = mode;
|
|
|
|
coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
|
|
|
|
}
|
|
|
|
|
2009-05-17 17:02:46 +08:00
|
|
|
if (rc < 0)
|
2008-06-20 09:07:23 +08:00
|
|
|
sms_err("return error code %d.", rc);
|
2008-05-20 05:56:13 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* calls device handler to get current mode of operation
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
|
|
|
* @return current mode
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
int smscore_get_device_mode(struct smscore_device_t *coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
|
|
|
return coredev->mode;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_get_device_mode);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-14 11:43:26 +08:00
|
|
|
/**
|
|
|
|
* find client by response id & type within the clients list.
|
|
|
|
* return client handle or NULL.
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-06-14 11:43:26 +08:00
|
|
|
* @param data_type client data type (SMS_DONT_CARE for all types)
|
2008-06-16 02:14:13 +08:00
|
|
|
* @param id client id (SMS_DONT_CARE for all id)
|
2008-06-14 11:43:26 +08:00
|
|
|
*
|
|
|
|
*/
|
2008-06-21 13:44:02 +08:00
|
|
|
static struct
|
|
|
|
smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
|
2008-06-16 03:50:11 +08:00
|
|
|
int data_type, int id)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_client_t *client = NULL;
|
2008-05-20 05:56:13 +08:00
|
|
|
struct list_head *next, *first;
|
|
|
|
unsigned long flags;
|
2008-06-14 11:43:26 +08:00
|
|
|
struct list_head *firstid, *nextid;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
spin_lock_irqsave(&coredev->clientslock, flags);
|
|
|
|
first = &coredev->clients;
|
2008-06-16 02:14:13 +08:00
|
|
|
for (next = first->next;
|
|
|
|
(next != first) && !client;
|
|
|
|
next = next->next) {
|
2008-06-16 04:52:24 +08:00
|
|
|
firstid = &((struct smscore_client_t *)next)->idlist;
|
2008-06-16 02:14:13 +08:00
|
|
|
for (nextid = firstid->next;
|
|
|
|
nextid != firstid;
|
|
|
|
nextid = nextid->next) {
|
2008-06-16 04:52:24 +08:00
|
|
|
if ((((struct smscore_idlist_t *)nextid)->id == id) &&
|
|
|
|
(((struct smscore_idlist_t *)nextid)->data_type == data_type ||
|
|
|
|
(((struct smscore_idlist_t *)nextid)->data_type == 0))) {
|
|
|
|
client = (struct smscore_client_t *) next;
|
2008-06-16 02:14:13 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&coredev->clientslock, flags);
|
|
|
|
return client;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* find client by response id/type, call clients onresponse handler
|
|
|
|
* return buffer to pool on error
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param cb pointer to response buffer descriptor
|
|
|
|
*
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
void smscore_onresponse(struct smscore_device_t *coredev,
|
2009-05-12 23:28:46 +08:00
|
|
|
struct smscore_buffer_t *cb) {
|
|
|
|
struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
|
|
|
|
+ cb->offset);
|
|
|
|
struct smscore_client_t *client;
|
2008-05-20 05:56:13 +08:00
|
|
|
int rc = -EBUSY;
|
2008-06-16 06:27:35 +08:00
|
|
|
static unsigned long last_sample_time; /* = 0; */
|
|
|
|
static int data_total; /* = 0; */
|
2008-05-20 05:56:13 +08:00
|
|
|
unsigned long time_now = jiffies_to_msecs(jiffies);
|
|
|
|
|
|
|
|
if (!last_sample_time)
|
|
|
|
last_sample_time = time_now;
|
|
|
|
|
2008-06-16 02:52:43 +08:00
|
|
|
if (time_now - last_sample_time > 10000) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("\ndata rate %d bytes/secs",
|
2008-06-19 12:15:46 +08:00
|
|
|
(int)((data_total * 1000) /
|
|
|
|
(time_now - last_sample_time)));
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
last_sample_time = time_now;
|
|
|
|
data_total = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
data_total += cb->size;
|
2009-05-12 23:28:46 +08:00
|
|
|
/* Do we need to re-route? */
|
|
|
|
if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
|
|
|
|
(phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
|
|
|
|
if (coredev->mode == DEVICE_MODE_DVBT_BDA)
|
|
|
|
phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* If no client registered for type & id,
|
|
|
|
* check for control client where type is not registered */
|
2008-05-20 05:56:13 +08:00
|
|
|
if (client)
|
|
|
|
rc = client->onresponse_handler(client->context, cb);
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (rc < 0) {
|
|
|
|
switch (phdr->msgType) {
|
|
|
|
case MSG_SMS_GET_VERSION_EX_RES:
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct SmsVersionRes_ST *ver =
|
|
|
|
(struct SmsVersionRes_ST *) phdr;
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("MSG_SMS_GET_VERSION_EX_RES "
|
|
|
|
"id %d prots 0x%x ver %d.%d",
|
2008-06-19 12:15:46 +08:00
|
|
|
ver->FirmwareId, ver->SupportedProtocols,
|
|
|
|
ver->RomVersionMajor, ver->RomVersionMinor);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
coredev->mode = ver->FirmwareId == 255 ?
|
|
|
|
DEVICE_MODE_NONE : ver->FirmwareId;
|
|
|
|
coredev->modes_supported = ver->SupportedProtocols;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
complete(&coredev->version_ex_done);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MSG_SMS_INIT_DEVICE_RES:
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("MSG_SMS_INIT_DEVICE_RES");
|
2008-06-16 02:14:13 +08:00
|
|
|
complete(&coredev->init_device_done);
|
|
|
|
break;
|
|
|
|
case MSG_SW_RELOAD_START_RES:
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("MSG_SW_RELOAD_START_RES");
|
2008-06-16 02:14:13 +08:00
|
|
|
complete(&coredev->reload_start_done);
|
|
|
|
break;
|
|
|
|
case MSG_SMS_DATA_DOWNLOAD_RES:
|
|
|
|
complete(&coredev->data_download_done);
|
|
|
|
break;
|
|
|
|
case MSG_SW_RELOAD_EXEC_RES:
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("MSG_SW_RELOAD_EXEC_RES");
|
2008-06-16 02:14:13 +08:00
|
|
|
break;
|
|
|
|
case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
|
2008-06-16 02:14:13 +08:00
|
|
|
complete(&coredev->trigger_done);
|
|
|
|
break;
|
|
|
|
case MSG_SMS_SLEEP_RESUME_COMP_IND:
|
|
|
|
complete(&coredev->resume_done);
|
|
|
|
break;
|
2009-05-19 23:52:58 +08:00
|
|
|
case MSG_SMS_GPIO_CONFIG_EX_RES:
|
|
|
|
sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
|
|
|
|
complete(&coredev->gpio_configuration_done);
|
|
|
|
break;
|
|
|
|
case MSG_SMS_GPIO_SET_LEVEL_RES:
|
|
|
|
sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
|
|
|
|
complete(&coredev->gpio_set_level_done);
|
|
|
|
break;
|
|
|
|
case MSG_SMS_GPIO_GET_LEVEL_RES:
|
|
|
|
{
|
|
|
|
u32 *msgdata = (u32 *) phdr;
|
|
|
|
coredev->gpio_get_res = msgdata[1];
|
|
|
|
sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
|
|
|
|
coredev->gpio_get_res);
|
|
|
|
complete(&coredev->gpio_get_level_done);
|
|
|
|
break;
|
|
|
|
}
|
2009-05-15 03:29:35 +08:00
|
|
|
case MSG_SMS_START_IR_RES:
|
|
|
|
complete(&coredev->ir_init_done);
|
|
|
|
break;
|
|
|
|
case MSG_SMS_IR_SAMPLES_IND:
|
|
|
|
sms_ir_event(coredev,
|
|
|
|
(const char *)
|
|
|
|
((char *)phdr
|
|
|
|
+ sizeof(struct SmsMsgHdr_ST)),
|
|
|
|
(int)phdr->msgLength
|
|
|
|
- sizeof(struct SmsMsgHdr_ST));
|
|
|
|
break;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
default:
|
|
|
|
break;
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
smscore_putbuffer(coredev, cb);
|
|
|
|
}
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_onresponse);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* return pointer to next free buffer descriptor from core pool
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
|
|
|
* @return pointer to descriptor on success, NULL on error.
|
|
|
|
*/
|
2010-08-24 20:52:36 +08:00
|
|
|
|
|
|
|
struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_buffer_t *cb = NULL;
|
2008-05-20 05:56:13 +08:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&coredev->bufferslock, flags);
|
2010-08-24 20:52:36 +08:00
|
|
|
if (!list_empty(&coredev->buffers)) {
|
|
|
|
cb = (struct smscore_buffer_t *) coredev->buffers.next;
|
|
|
|
list_del(&cb->entry);
|
2010-07-28 02:42:40 +08:00
|
|
|
}
|
2010-08-24 20:52:36 +08:00
|
|
|
spin_unlock_irqrestore(&coredev->bufferslock, flags);
|
|
|
|
return cb;
|
|
|
|
}
|
2009-05-17 16:59:37 +08:00
|
|
|
|
2010-08-24 20:52:36 +08:00
|
|
|
struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
|
|
|
|
{
|
|
|
|
struct smscore_buffer_t *cb = NULL;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2010-08-24 20:52:36 +08:00
|
|
|
wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
return cb;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_getbuffer);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* return buffer descriptor to a pool
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param coredev pointer to a coredev object returned by
|
|
|
|
* smscore_register_device
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param cb pointer buffer descriptor
|
|
|
|
*
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
void smscore_putbuffer(struct smscore_device_t *coredev,
|
2009-05-17 16:59:37 +08:00
|
|
|
struct smscore_buffer_t *cb) {
|
|
|
|
wake_up_interruptible(&coredev->buffer_mng_waitq);
|
2008-05-20 05:56:13 +08:00
|
|
|
list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_putbuffer);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-21 13:44:02 +08:00
|
|
|
static int smscore_validate_client(struct smscore_device_t *coredev,
|
|
|
|
struct smscore_client_t *client,
|
|
|
|
int data_type, int id)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_idlist_t *listentry;
|
|
|
|
struct smscore_client_t *registered_client;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!client) {
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_err("bad parameter.");
|
2011-07-06 23:55:29 +08:00
|
|
|
return -EINVAL;
|
2008-06-14 11:43:26 +08:00
|
|
|
}
|
|
|
|
registered_client = smscore_find_client(coredev, data_type, id);
|
2008-06-16 02:52:43 +08:00
|
|
|
if (registered_client == client)
|
2008-05-20 05:56:13 +08:00
|
|
|
return 0;
|
2008-06-16 02:52:43 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (registered_client) {
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_err("The msg ID already registered to another client.");
|
2008-06-14 11:43:26 +08:00
|
|
|
return -EEXIST;
|
|
|
|
}
|
2008-06-16 04:52:24 +08:00
|
|
|
listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!listentry) {
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_err("Can't allocate memory for client id.");
|
2008-05-20 05:56:13 +08:00
|
|
|
return -ENOMEM;
|
2008-06-14 11:43:26 +08:00
|
|
|
}
|
|
|
|
listentry->id = id;
|
|
|
|
listentry->data_type = data_type;
|
2008-06-16 02:14:13 +08:00
|
|
|
list_add_locked(&listentry->entry, &client->idlist,
|
|
|
|
&coredev->clientslock);
|
2008-05-20 05:56:13 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* creates smsclient object, check that id is taken by another client
|
|
|
|
*
|
|
|
|
* @param coredev pointer to a coredev object from clients hotplug
|
|
|
|
* @param initial_id all messages with this id would be sent to this client
|
|
|
|
* @param data_type all messages of this type would be sent to this client
|
2008-06-16 04:36:00 +08:00
|
|
|
* @param onresponse_handler client handler that is called to
|
|
|
|
* process incoming messages
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param onremove_handler client handler that is called when device is removed
|
|
|
|
* @param context client-specific context
|
|
|
|
* @param client pointer to a value that receives created smsclient object
|
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
int smscore_register_client(struct smscore_device_t *coredev,
|
|
|
|
struct smsclient_params_t *params,
|
|
|
|
struct smscore_client_t **client)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_client_t *newclient;
|
2008-06-16 02:14:13 +08:00
|
|
|
/* check that no other channel with same parameters exists */
|
|
|
|
if (smscore_find_client(coredev, params->data_type,
|
|
|
|
params->initial_id)) {
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_err("Client already exist.");
|
2008-05-20 05:56:13 +08:00
|
|
|
return -EEXIST;
|
2008-06-14 11:43:26 +08:00
|
|
|
}
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 04:52:24 +08:00
|
|
|
newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
|
2008-06-16 02:14:13 +08:00
|
|
|
if (!newclient) {
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_err("Failed to allocate memory for client.");
|
2008-06-14 11:43:26 +08:00
|
|
|
return -ENOMEM;
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
INIT_LIST_HEAD(&newclient->idlist);
|
2008-05-20 05:56:13 +08:00
|
|
|
newclient->coredev = coredev;
|
|
|
|
newclient->onresponse_handler = params->onresponse_handler;
|
|
|
|
newclient->onremove_handler = params->onremove_handler;
|
|
|
|
newclient->context = params->context;
|
2008-06-16 02:14:13 +08:00
|
|
|
list_add_locked(&newclient->entry, &coredev->clients,
|
|
|
|
&coredev->clientslock);
|
|
|
|
smscore_validate_client(coredev, newclient, params->data_type,
|
|
|
|
params->initial_id);
|
2008-05-20 05:56:13 +08:00
|
|
|
*client = newclient;
|
2008-06-20 09:15:38 +08:00
|
|
|
sms_debug("%p %d %d", params->context, params->data_type,
|
|
|
|
params->initial_id);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_register_client);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* frees smsclient object and all subclients associated with it
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param client pointer to smsclient object returned by
|
|
|
|
* smscore_register_client
|
2008-05-20 05:56:13 +08:00
|
|
|
*
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
void smscore_unregister_client(struct smscore_client_t *client)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_t *coredev = client->coredev;
|
2008-05-20 05:56:13 +08:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&coredev->clientslock, flags);
|
|
|
|
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
while (!list_empty(&client->idlist)) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_idlist_t *identry =
|
|
|
|
(struct smscore_idlist_t *) client->idlist.next;
|
2008-06-16 02:14:13 +08:00
|
|
|
list_del(&identry->entry);
|
|
|
|
kfree(identry);
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_info("%p", client->context);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
list_del(&client->entry);
|
|
|
|
kfree(client);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&coredev->clientslock, flags);
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smscore_unregister_client);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* verifies that source id is not taken by another client,
|
|
|
|
* calls device handler to send requests to the device
|
|
|
|
*
|
2008-06-16 03:50:11 +08:00
|
|
|
* @param client pointer to smsclient object returned by
|
|
|
|
* smscore_register_client
|
2008-05-20 05:56:13 +08:00
|
|
|
* @param buffer pointer to a request buffer
|
|
|
|
* @param size size (in bytes) of request buffer
|
|
|
|
*
|
|
|
|
* @return 0 on success, <0 on error.
|
|
|
|
*/
|
2008-06-16 04:52:24 +08:00
|
|
|
int smsclient_sendrequest(struct smscore_client_t *client,
|
|
|
|
void *buffer, size_t size)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_t *coredev;
|
|
|
|
struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
|
2008-06-14 11:43:26 +08:00
|
|
|
int rc;
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
if (client == NULL) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("Got NULL client");
|
2008-06-14 11:43:26 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
coredev = client->coredev;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
/* check that no other channel with same id exists */
|
|
|
|
if (coredev == NULL) {
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_err("Got NULL coredev");
|
2008-06-14 11:43:26 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2008-06-16 02:14:13 +08:00
|
|
|
rc = smscore_validate_client(client->coredev, client, 0,
|
|
|
|
phdr->msgSrcId);
|
2008-05-20 05:56:13 +08:00
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
return coredev->sendrequest_handler(coredev->context, buffer, size);
|
|
|
|
}
|
2009-02-27 05:32:36 +08:00
|
|
|
EXPORT_SYMBOL_GPL(smsclient_sendrequest);
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
|
2010-06-11 18:17:01 +08:00
|
|
|
/* old GPIO managements implementation */
|
2008-11-17 05:01:58 +08:00
|
|
|
int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
|
2009-05-19 22:49:19 +08:00
|
|
|
struct smscore_config_gpio *pinconfig)
|
2008-11-17 05:01:58 +08:00
|
|
|
{
|
|
|
|
struct {
|
|
|
|
struct SmsMsgHdr_ST hdr;
|
|
|
|
u32 data[6];
|
|
|
|
} msg;
|
|
|
|
|
|
|
|
if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
|
|
|
|
msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
|
|
|
|
msg.hdr.msgDstId = HIF_TASK;
|
|
|
|
msg.hdr.msgFlags = 0;
|
|
|
|
msg.hdr.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
|
|
|
|
msg.hdr.msgLength = sizeof(msg);
|
|
|
|
|
|
|
|
msg.data[0] = pin;
|
|
|
|
msg.data[1] = pinconfig->pullupdown;
|
|
|
|
|
|
|
|
/* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
|
|
|
|
msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
|
|
|
|
|
|
|
|
switch (pinconfig->outputdriving) {
|
|
|
|
case SMS_GPIO_OUTPUTDRIVING_16mA:
|
|
|
|
msg.data[3] = 7; /* Nova - 16mA */
|
|
|
|
break;
|
|
|
|
case SMS_GPIO_OUTPUTDRIVING_12mA:
|
|
|
|
msg.data[3] = 5; /* Nova - 11mA */
|
|
|
|
break;
|
|
|
|
case SMS_GPIO_OUTPUTDRIVING_8mA:
|
|
|
|
msg.data[3] = 3; /* Nova - 7mA */
|
|
|
|
break;
|
|
|
|
case SMS_GPIO_OUTPUTDRIVING_4mA:
|
|
|
|
default:
|
|
|
|
msg.data[3] = 2; /* Nova - 4mA */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg.data[4] = pinconfig->direction;
|
|
|
|
msg.data[5] = 0;
|
|
|
|
} else /* TODO: SMS_DEVICE_FAMILY1 */
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return coredev->sendrequest_handler(coredev->context,
|
|
|
|
&msg, sizeof(msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
struct SmsMsgHdr_ST hdr;
|
|
|
|
u32 data[3];
|
|
|
|
} msg;
|
|
|
|
|
|
|
|
if (pin > MAX_GPIO_PIN_NUMBER)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
|
|
|
|
msg.hdr.msgDstId = HIF_TASK;
|
|
|
|
msg.hdr.msgFlags = 0;
|
|
|
|
msg.hdr.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
|
|
|
|
msg.hdr.msgLength = sizeof(msg);
|
|
|
|
|
|
|
|
msg.data[0] = pin;
|
|
|
|
msg.data[1] = level ? 1 : 0;
|
|
|
|
msg.data[2] = 0;
|
|
|
|
|
|
|
|
return coredev->sendrequest_handler(coredev->context,
|
|
|
|
&msg, sizeof(msg));
|
|
|
|
}
|
|
|
|
|
2009-07-23 14:31:31 +08:00
|
|
|
/* new GPIO management implementation */
|
2009-05-19 22:49:19 +08:00
|
|
|
static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
|
|
|
|
u32 *pGroupNum, u32 *pGroupCfg) {
|
|
|
|
|
|
|
|
*pGroupCfg = 1;
|
|
|
|
|
2009-10-23 18:59:42 +08:00
|
|
|
if (PinNum <= 1) {
|
2009-05-19 22:49:19 +08:00
|
|
|
*pTranslatedPinNum = 0;
|
|
|
|
*pGroupNum = 9;
|
|
|
|
*pGroupCfg = 2;
|
|
|
|
} else if (PinNum >= 2 && PinNum <= 6) {
|
|
|
|
*pTranslatedPinNum = 2;
|
|
|
|
*pGroupNum = 0;
|
|
|
|
*pGroupCfg = 2;
|
|
|
|
} else if (PinNum >= 7 && PinNum <= 11) {
|
|
|
|
*pTranslatedPinNum = 7;
|
|
|
|
*pGroupNum = 1;
|
|
|
|
} else if (PinNum >= 12 && PinNum <= 15) {
|
|
|
|
*pTranslatedPinNum = 12;
|
|
|
|
*pGroupNum = 2;
|
|
|
|
*pGroupCfg = 3;
|
|
|
|
} else if (PinNum == 16) {
|
|
|
|
*pTranslatedPinNum = 16;
|
|
|
|
*pGroupNum = 23;
|
|
|
|
} else if (PinNum >= 17 && PinNum <= 24) {
|
|
|
|
*pTranslatedPinNum = 17;
|
|
|
|
*pGroupNum = 3;
|
|
|
|
} else if (PinNum == 25) {
|
|
|
|
*pTranslatedPinNum = 25;
|
|
|
|
*pGroupNum = 6;
|
|
|
|
} else if (PinNum >= 26 && PinNum <= 28) {
|
|
|
|
*pTranslatedPinNum = 26;
|
|
|
|
*pGroupNum = 4;
|
|
|
|
} else if (PinNum == 29) {
|
|
|
|
*pTranslatedPinNum = 29;
|
|
|
|
*pGroupNum = 5;
|
|
|
|
*pGroupCfg = 2;
|
|
|
|
} else if (PinNum == 30) {
|
|
|
|
*pTranslatedPinNum = 30;
|
|
|
|
*pGroupNum = 8;
|
|
|
|
} else if (PinNum == 31) {
|
|
|
|
*pTranslatedPinNum = 31;
|
|
|
|
*pGroupNum = 17;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
*pGroupCfg <<= 24;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
|
|
|
|
struct smscore_gpio_config *pGpioConfig) {
|
|
|
|
|
|
|
|
u32 totalLen;
|
2009-06-14 17:47:35 +08:00
|
|
|
u32 TranslatedPinNum = 0;
|
|
|
|
u32 GroupNum = 0;
|
2009-05-19 22:49:19 +08:00
|
|
|
u32 ElectricChar;
|
|
|
|
u32 groupCfg;
|
|
|
|
void *buffer;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
struct SetGpioMsg {
|
|
|
|
struct SmsMsgHdr_ST xMsgHeader;
|
|
|
|
u32 msgData[6];
|
|
|
|
} *pMsg;
|
|
|
|
|
|
|
|
|
|
|
|
if (PinNum > MAX_GPIO_PIN_NUMBER)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (pGpioConfig == NULL)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
|
|
|
|
|
|
|
|
buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
|
|
|
|
GFP_KERNEL | GFP_DMA);
|
|
|
|
if (!buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
|
|
|
|
|
|
|
|
pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
|
|
|
|
pMsg->xMsgHeader.msgDstId = HIF_TASK;
|
|
|
|
pMsg->xMsgHeader.msgFlags = 0;
|
|
|
|
pMsg->xMsgHeader.msgLength = (u16) totalLen;
|
|
|
|
pMsg->msgData[0] = PinNum;
|
|
|
|
|
|
|
|
if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
|
|
|
|
pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
|
|
|
|
if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
|
2010-01-07 00:45:27 +08:00
|
|
|
&groupCfg) != 0) {
|
|
|
|
rc = -EINVAL;
|
|
|
|
goto free;
|
|
|
|
}
|
2009-05-19 22:49:19 +08:00
|
|
|
|
|
|
|
pMsg->msgData[1] = TranslatedPinNum;
|
|
|
|
pMsg->msgData[2] = GroupNum;
|
|
|
|
ElectricChar = (pGpioConfig->PullUpDown)
|
|
|
|
| (pGpioConfig->InputCharacteristics << 2)
|
|
|
|
| (pGpioConfig->OutputSlewRate << 3)
|
|
|
|
| (pGpioConfig->OutputDriving << 4);
|
|
|
|
pMsg->msgData[3] = ElectricChar;
|
|
|
|
pMsg->msgData[4] = pGpioConfig->Direction;
|
|
|
|
pMsg->msgData[5] = groupCfg;
|
|
|
|
} else {
|
|
|
|
pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
|
|
|
|
pMsg->msgData[1] = pGpioConfig->PullUpDown;
|
|
|
|
pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
|
|
|
|
pMsg->msgData[3] = pGpioConfig->OutputDriving;
|
|
|
|
pMsg->msgData[4] = pGpioConfig->Direction;
|
|
|
|
pMsg->msgData[5] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
|
|
|
|
rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
|
|
|
|
&coredev->gpio_configuration_done);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
if (rc == -ETIME)
|
|
|
|
sms_err("smscore_gpio_configure timeout");
|
|
|
|
else
|
|
|
|
sms_err("smscore_gpio_configure error");
|
|
|
|
}
|
2010-01-07 00:45:27 +08:00
|
|
|
free:
|
2009-05-19 22:49:19 +08:00
|
|
|
kfree(buffer);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
|
|
|
|
u8 NewLevel) {
|
|
|
|
|
|
|
|
u32 totalLen;
|
|
|
|
int rc;
|
|
|
|
void *buffer;
|
|
|
|
|
|
|
|
struct SetGpioMsg {
|
|
|
|
struct SmsMsgHdr_ST xMsgHeader;
|
|
|
|
u32 msgData[3]; /* keep it 3 ! */
|
|
|
|
} *pMsg;
|
|
|
|
|
2010-08-28 23:41:05 +08:00
|
|
|
if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER))
|
2009-05-19 22:49:19 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
totalLen = sizeof(struct SmsMsgHdr_ST) +
|
|
|
|
(3 * sizeof(u32)); /* keep it 3 ! */
|
|
|
|
|
|
|
|
buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
|
|
|
|
GFP_KERNEL | GFP_DMA);
|
|
|
|
if (!buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
|
|
|
|
|
|
|
|
pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
|
|
|
|
pMsg->xMsgHeader.msgDstId = HIF_TASK;
|
|
|
|
pMsg->xMsgHeader.msgFlags = 0;
|
|
|
|
pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
|
|
|
|
pMsg->xMsgHeader.msgLength = (u16) totalLen;
|
|
|
|
pMsg->msgData[0] = PinNum;
|
|
|
|
pMsg->msgData[1] = NewLevel;
|
|
|
|
|
|
|
|
/* Send message to SMS */
|
|
|
|
smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
|
|
|
|
rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
|
|
|
|
&coredev->gpio_set_level_done);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
if (rc == -ETIME)
|
|
|
|
sms_err("smscore_gpio_set_level timeout");
|
|
|
|
else
|
|
|
|
sms_err("smscore_gpio_set_level error");
|
|
|
|
}
|
|
|
|
kfree(buffer);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
|
|
|
|
u8 *level) {
|
|
|
|
|
|
|
|
u32 totalLen;
|
|
|
|
int rc;
|
|
|
|
void *buffer;
|
|
|
|
|
|
|
|
struct SetGpioMsg {
|
|
|
|
struct SmsMsgHdr_ST xMsgHeader;
|
|
|
|
u32 msgData[2];
|
|
|
|
} *pMsg;
|
|
|
|
|
|
|
|
|
|
|
|
if (PinNum > MAX_GPIO_PIN_NUMBER)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
|
|
|
|
|
|
|
|
buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
|
|
|
|
GFP_KERNEL | GFP_DMA);
|
|
|
|
if (!buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
|
|
|
|
|
|
|
|
pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
|
|
|
|
pMsg->xMsgHeader.msgDstId = HIF_TASK;
|
|
|
|
pMsg->xMsgHeader.msgFlags = 0;
|
|
|
|
pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
|
|
|
|
pMsg->xMsgHeader.msgLength = (u16) totalLen;
|
|
|
|
pMsg->msgData[0] = PinNum;
|
|
|
|
pMsg->msgData[1] = 0;
|
|
|
|
|
|
|
|
/* Send message to SMS */
|
|
|
|
smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
|
|
|
|
rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
|
|
|
|
&coredev->gpio_get_level_done);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
if (rc == -ETIME)
|
|
|
|
sms_err("smscore_gpio_get_level timeout");
|
|
|
|
else
|
|
|
|
sms_err("smscore_gpio_get_level error");
|
|
|
|
}
|
|
|
|
kfree(buffer);
|
|
|
|
|
|
|
|
/* Its a race between other gpio_get_level() and the copy of the single
|
|
|
|
* global 'coredev->gpio_get_res' to the function's variable 'level'
|
|
|
|
*/
|
|
|
|
*level = coredev->gpio_get_res;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-07-22 10:17:36 +08:00
|
|
|
static int __init smscore_module_init(void)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
2008-05-20 06:09:21 +08:00
|
|
|
int rc = 0;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
INIT_LIST_HEAD(&g_smscore_notifyees);
|
|
|
|
INIT_LIST_HEAD(&g_smscore_devices);
|
|
|
|
kmutex_init(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&g_smscore_registry);
|
|
|
|
kmutex_init(&g_smscore_registrylock);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-07-22 10:17:36 +08:00
|
|
|
static void __exit smscore_module_exit(void)
|
2008-05-20 05:56:13 +08:00
|
|
|
{
|
|
|
|
kmutex_lock(&g_smscore_deviceslock);
|
2008-06-16 02:14:13 +08:00
|
|
|
while (!list_empty(&g_smscore_notifyees)) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_device_notifyee_t *notifyee =
|
|
|
|
(struct smscore_device_notifyee_t *)
|
|
|
|
g_smscore_notifyees.next;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
list_del(¬ifyee->entry);
|
|
|
|
kfree(notifyee);
|
|
|
|
}
|
|
|
|
kmutex_unlock(&g_smscore_deviceslock);
|
|
|
|
|
|
|
|
kmutex_lock(&g_smscore_registrylock);
|
2008-06-16 02:14:13 +08:00
|
|
|
while (!list_empty(&g_smscore_registry)) {
|
2008-06-16 04:52:24 +08:00
|
|
|
struct smscore_registry_entry_t *entry =
|
|
|
|
(struct smscore_registry_entry_t *)
|
|
|
|
g_smscore_registry.next;
|
2008-05-20 05:56:13 +08:00
|
|
|
|
|
|
|
list_del(&entry->entry);
|
|
|
|
kfree(entry);
|
|
|
|
}
|
|
|
|
kmutex_unlock(&g_smscore_registrylock);
|
|
|
|
|
2008-06-20 07:35:21 +08:00
|
|
|
sms_debug("");
|
2008-05-20 05:56:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module_init(smscore_module_init);
|
|
|
|
module_exit(smscore_module_exit);
|
|
|
|
|
V4L/DVB (10750): import changes from Siano
Import the following changes from Uri Shkolnik
* Two-ways merge with Siano internal repository
* Continuing with DVB sub-system separation
* kconfig and makefile updates
* Code cleanup
This is a work-in-progress sync with Siano's internal repository.
Some changes had to be altered or dropped in order not to break the build.
This breaks normal operation for the current driver, but it is being committed
now for tracking purposes.
These changes introduce the following checkpatch.pl violations:
ERROR: do not use C99 // comments
156: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1373:
+//#ifdef DVB_CORE
ERROR: do not use C99 // comments
157: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1374:
+// smsdvb_unregister();
ERROR: do not use C99 // comments
158: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1375:
+//#endif
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
163: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1380:
+EXPORT_SYMBOL(smscore_onresponse);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
164: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1381:
+EXPORT_SYMBOL(sms_get_board);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
165: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1382:
+EXPORT_SYMBOL(sms_debug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
166: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1383:
+EXPORT_SYMBOL(smscore_putbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
167: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1384:
+EXPORT_SYMBOL(smscore_registry_getmode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
168: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1385:
+EXPORT_SYMBOL(smscore_register_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
169: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1386:
+EXPORT_SYMBOL(smscore_set_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
170: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1387:
+EXPORT_SYMBOL(smscore_start_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
171: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1388:
+EXPORT_SYMBOL(smsusb_id_table);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
172: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1389:
+EXPORT_SYMBOL(smscore_unregister_device);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
173: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1390:
+EXPORT_SYMBOL(smscore_getbuffer);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
174: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1391:
+EXPORT_SYMBOL(smscore_get_device_mode);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
175: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1392:
+EXPORT_SYMBOL(smscore_register_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
176: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1393:
+EXPORT_SYMBOL(smscore_unregister_hotplug);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
177: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1394:
+EXPORT_SYMBOL(smsclient_sendrequest);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
178: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1395:
+EXPORT_SYMBOL(smscore_unregister_client);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
179: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1396:
+EXPORT_SYMBOL(smscore_get_board_id);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
180: FILE: linux/drivers/media/dvb/siano/smscoreapi.c:1397:
+EXPORT_SYMBOL(smscore_register_hotplug);
WARNING: line over 80 characters
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
ERROR: "foo* bar" should be "foo *bar"
391: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:398:
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode, char* filename);
WARNING: line over 80 characters
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: "foo* bar" should be "foo *bar"
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
ERROR: space required after that ',' (ctx:VxV)
392: FILE: linux/drivers/media/dvb/siano/smscoreapi.h:399:
+extern int smscore_send_fw_file(struct smscore_device_t *coredev, u8* ufwbuf,int size);
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
489: FILE: linux/drivers/media/dvb/siano/smsusb.c:443:
+ printk(KERN_INFO"%s Entering status %d.\n", __FUNCTION__, msg.event);
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
501: FILE: linux/drivers/media/dvb/siano/smsusb.c:455:
+ printk(KERN_INFO "%s Entering.\n", __FUNCTION__);
ERROR: space prohibited before that '++' (ctx:WxB)
505: FILE: linux/drivers/media/dvb/siano/smsusb.c:459:
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i ++)
^
WARNING: __func__ should be used instead of gcc specific __FUNCTION__
517: FILE: linux/drivers/media/dvb/siano/smsusb.c:471:
+ __FUNCTION__, rc);
total: 7 errors, 23 warnings, 524 lines checked
Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
2008-08-31 11:44:04 +08:00
|
|
|
MODULE_DESCRIPTION("Siano MDTV Core module");
|
|
|
|
MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
|
2008-05-20 05:56:13 +08:00
|
|
|
MODULE_LICENSE("GPL");
|