2 * Siano core API module
4 * This file contains implementation for the interface to sms core component
6 * author: Anatoly Greenblat
8 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 3 as
12 * published by the Free Software Foundation;
14 * Software distributed under the License is distributed on an "AS IS"
15 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
17 * See the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/delay.h>
32 #include <linux/firmware.h>
34 #include "smscoreapi.h"
35 #include "sms-cards.h"
38 module_param_named(debug
, sms_debug
, int, 0644);
39 MODULE_PARM_DESC(debug
, "set debug level (info=1, adv=2 (or-able))");
41 struct smscore_device_notifyee_t
{
42 struct list_head entry
;
46 struct smscore_idlist_t
{
47 struct list_head entry
;
52 struct smscore_client_t
{
53 struct list_head entry
;
54 struct smscore_device_t
*coredev
;
56 struct list_head idlist
;
57 onresponse_t onresponse_handler
;
58 onremove_t onremove_handler
;
61 struct smscore_device_t
{
62 struct list_head entry
;
64 struct list_head clients
;
65 struct list_head subclients
;
66 spinlock_t clientslock
;
68 struct list_head buffers
;
69 spinlock_t bufferslock
;
73 int common_buffer_size
;
74 dma_addr_t common_buffer_phys
;
77 struct device
*device
;
80 unsigned long device_flags
;
82 setmode_t setmode_handler
;
83 detectmode_t detectmode_handler
;
84 sendrequest_t sendrequest_handler
;
85 preload_t preload_handler
;
86 postload_t postload_handler
;
88 int mode
, modes_supported
;
90 struct completion version_ex_done
, data_download_done
, trigger_done
;
91 struct completion init_device_done
, reload_start_done
, resume_done
;
96 void smscore_set_board_id(struct smscore_device_t
*core
, int id
)
101 int smscore_get_board_id(struct smscore_device_t
*core
)
103 return core
->board_id
;
106 struct smscore_registry_entry_t
{
107 struct list_head entry
;
110 enum sms_device_type_st type
;
113 static struct list_head g_smscore_notifyees
;
114 static struct list_head g_smscore_devices
;
115 static struct mutex g_smscore_deviceslock
;
117 static struct list_head g_smscore_registry
;
118 static struct mutex g_smscore_registrylock
;
120 static int default_mode
= 4;
122 module_param(default_mode
, int, 0644);
123 MODULE_PARM_DESC(default_mode
, "default firmware id (device mode)");
125 static struct smscore_registry_entry_t
*smscore_find_registry(char *devpath
)
127 struct smscore_registry_entry_t
*entry
;
128 struct list_head
*next
;
130 kmutex_lock(&g_smscore_registrylock
);
131 for (next
= g_smscore_registry
.next
;
132 next
!= &g_smscore_registry
;
134 entry
= (struct smscore_registry_entry_t
*) next
;
135 if (!strcmp(entry
->devpath
, devpath
)) {
136 kmutex_unlock(&g_smscore_registrylock
);
140 entry
= (struct smscore_registry_entry_t
*)
141 kmalloc(sizeof(struct smscore_registry_entry_t
),
144 entry
->mode
= default_mode
;
145 strcpy(entry
->devpath
, devpath
);
146 list_add(&entry
->entry
, &g_smscore_registry
);
148 sms_err("failed to create smscore_registry.");
149 kmutex_unlock(&g_smscore_registrylock
);
153 int smscore_registry_getmode(char *devpath
)
155 struct smscore_registry_entry_t
*entry
;
157 entry
= smscore_find_registry(devpath
);
161 sms_err("No registry found.");
166 static enum sms_device_type_st
smscore_registry_gettype(char *devpath
)
168 struct smscore_registry_entry_t
*entry
;
170 entry
= smscore_find_registry(devpath
);
174 sms_err("No registry found.");
179 void smscore_registry_setmode(char *devpath
, int mode
)
181 struct smscore_registry_entry_t
*entry
;
183 entry
= smscore_find_registry(devpath
);
187 sms_err("No registry found.");
190 static void smscore_registry_settype(char *devpath
,
191 enum sms_device_type_st type
)
193 struct smscore_registry_entry_t
*entry
;
195 entry
= smscore_find_registry(devpath
);
199 sms_err("No registry found.");
203 static void list_add_locked(struct list_head
*new, struct list_head
*head
,
208 spin_lock_irqsave(lock
, flags
);
212 spin_unlock_irqrestore(lock
, flags
);
216 * register a client callback that called when device plugged in/unplugged
217 * NOTE: if devices exist callback is called immediately for each device
219 * @param hotplug callback
221 * @return 0 on success, <0 on error.
223 int smscore_register_hotplug(hotplug_t hotplug
)
225 struct smscore_device_notifyee_t
*notifyee
;
226 struct list_head
*next
, *first
;
229 kmutex_lock(&g_smscore_deviceslock
);
231 notifyee
= kmalloc(sizeof(struct smscore_device_notifyee_t
),
234 /* now notify callback about existing devices */
235 first
= &g_smscore_devices
;
236 for (next
= first
->next
;
237 next
!= first
&& !rc
;
239 struct smscore_device_t
*coredev
=
240 (struct smscore_device_t
*) next
;
241 rc
= hotplug(coredev
, coredev
->device
, 1);
245 notifyee
->hotplug
= hotplug
;
246 list_add(¬ifyee
->entry
, &g_smscore_notifyees
);
252 kmutex_unlock(&g_smscore_deviceslock
);
258 * unregister a client callback that called when device plugged in/unplugged
260 * @param hotplug callback
263 void smscore_unregister_hotplug(hotplug_t hotplug
)
265 struct list_head
*next
, *first
;
267 kmutex_lock(&g_smscore_deviceslock
);
269 first
= &g_smscore_notifyees
;
271 for (next
= first
->next
; next
!= first
;) {
272 struct smscore_device_notifyee_t
*notifyee
=
273 (struct smscore_device_notifyee_t
*) next
;
276 if (notifyee
->hotplug
== hotplug
) {
277 list_del(¬ifyee
->entry
);
282 kmutex_unlock(&g_smscore_deviceslock
);
285 static void smscore_notify_clients(struct smscore_device_t
*coredev
)
287 struct smscore_client_t
*client
;
289 /* the client must call smscore_unregister_client from remove handler */
290 while (!list_empty(&coredev
->clients
)) {
291 client
= (struct smscore_client_t
*) coredev
->clients
.next
;
292 client
->onremove_handler(client
->context
);
296 static int smscore_notify_callbacks(struct smscore_device_t
*coredev
,
297 struct device
*device
, int arrival
)
299 struct list_head
*next
, *first
;
302 /* note: must be called under g_deviceslock */
304 first
= &g_smscore_notifyees
;
306 for (next
= first
->next
; next
!= first
; next
= next
->next
) {
307 rc
= ((struct smscore_device_notifyee_t
*) next
)->
308 hotplug(coredev
, device
, arrival
);
317 smscore_buffer_t
*smscore_createbuffer(u8
*buffer
, void *common_buffer
,
318 dma_addr_t common_buffer_phys
)
320 struct smscore_buffer_t
*cb
=
321 kmalloc(sizeof(struct smscore_buffer_t
), GFP_KERNEL
);
323 sms_info("kmalloc(...) failed");
328 cb
->offset_in_common
= buffer
- (u8
*) common_buffer
;
329 cb
->phys
= common_buffer_phys
+ cb
->offset_in_common
;
335 * creates coredev object for a device, prepares buffers,
336 * creates buffer mappings, notifies registered hotplugs about new device.
338 * @param params device pointer to struct with device specific parameters
340 * @param coredev pointer to a value that receives created coredev object
342 * @return 0 on success, <0 on error.
344 int smscore_register_device(struct smsdevice_params_t
*params
,
345 struct smscore_device_t
**coredev
)
347 struct smscore_device_t
*dev
;
350 dev
= kzalloc(sizeof(struct smscore_device_t
), GFP_KERNEL
);
352 sms_info("kzalloc(...) failed");
356 /* init list entry so it could be safe in smscore_unregister_device */
357 INIT_LIST_HEAD(&dev
->entry
);
360 INIT_LIST_HEAD(&dev
->clients
);
361 INIT_LIST_HEAD(&dev
->buffers
);
364 spin_lock_init(&dev
->clientslock
);
365 spin_lock_init(&dev
->bufferslock
);
367 /* init completion events */
368 init_completion(&dev
->version_ex_done
);
369 init_completion(&dev
->data_download_done
);
370 init_completion(&dev
->trigger_done
);
371 init_completion(&dev
->init_device_done
);
372 init_completion(&dev
->reload_start_done
);
373 init_completion(&dev
->resume_done
);
375 /* alloc common buffer */
376 dev
->common_buffer_size
= params
->buffer_size
* params
->num_buffers
;
377 dev
->common_buffer
= dma_alloc_coherent(NULL
, dev
->common_buffer_size
,
378 &dev
->common_buffer_phys
,
379 GFP_KERNEL
| GFP_DMA
);
380 if (!dev
->common_buffer
) {
381 smscore_unregister_device(dev
);
385 /* prepare dma buffers */
386 for (buffer
= dev
->common_buffer
;
387 dev
->num_buffers
< params
->num_buffers
;
388 dev
->num_buffers
++, buffer
+= params
->buffer_size
) {
389 struct smscore_buffer_t
*cb
=
390 smscore_createbuffer(buffer
, dev
->common_buffer
,
391 dev
->common_buffer_phys
);
393 smscore_unregister_device(dev
);
397 smscore_putbuffer(dev
, cb
);
400 sms_info("allocated %d buffers", dev
->num_buffers
);
402 dev
->mode
= DEVICE_MODE_NONE
;
403 dev
->context
= params
->context
;
404 dev
->device
= params
->device
;
405 dev
->setmode_handler
= params
->setmode_handler
;
406 dev
->detectmode_handler
= params
->detectmode_handler
;
407 dev
->sendrequest_handler
= params
->sendrequest_handler
;
408 dev
->preload_handler
= params
->preload_handler
;
409 dev
->postload_handler
= params
->postload_handler
;
411 dev
->device_flags
= params
->flags
;
412 strcpy(dev
->devpath
, params
->devpath
);
414 smscore_registry_settype(dev
->devpath
, params
->device_type
);
416 /* add device to devices list */
417 kmutex_lock(&g_smscore_deviceslock
);
418 list_add(&dev
->entry
, &g_smscore_devices
);
419 kmutex_unlock(&g_smscore_deviceslock
);
423 sms_info("device %p created", dev
);
429 * sets initial device mode and notifies client hotplugs that device is ready
431 * @param coredev pointer to a coredev object returned by
432 * smscore_register_device
434 * @return 0 on success, <0 on error.
436 int smscore_start_device(struct smscore_device_t
*coredev
)
438 int rc
= smscore_set_device_mode(
439 coredev
, smscore_registry_getmode(coredev
->devpath
));
441 sms_info("set device mode faile , rc %d", rc
);
445 kmutex_lock(&g_smscore_deviceslock
);
447 rc
= smscore_notify_callbacks(coredev
, coredev
->device
, 1);
449 sms_info("device %p started, rc %d", coredev
, rc
);
451 kmutex_unlock(&g_smscore_deviceslock
);
456 static int smscore_sendrequest_and_wait(struct smscore_device_t
*coredev
,
457 void *buffer
, size_t size
,
458 struct completion
*completion
)
460 int rc
= coredev
->sendrequest_handler(coredev
->context
, buffer
, size
);
462 sms_info("sendrequest returned error %d", rc
);
466 return wait_for_completion_timeout(completion
,
467 msecs_to_jiffies(10000)) ?
471 static int smscore_load_firmware_family2(struct smscore_device_t
*coredev
,
472 void *buffer
, size_t size
)
474 struct SmsFirmware_ST
*firmware
= (struct SmsFirmware_ST
*) buffer
;
475 struct SmsMsgHdr_ST
*msg
;
476 u32 mem_address
= firmware
->StartAddress
;
477 u8
*payload
= firmware
->Payload
;
480 sms_info("loading FW to addr 0x%x size %d",
481 mem_address
, firmware
->Length
);
482 if (coredev
->preload_handler
) {
483 rc
= coredev
->preload_handler(coredev
->context
);
488 /* PAGE_SIZE buffer shall be enough and dma aligned */
489 msg
= kmalloc(PAGE_SIZE
, GFP_KERNEL
| GFP_DMA
);
493 if (coredev
->mode
!= DEVICE_MODE_NONE
) {
494 sms_debug("sending reload command.");
495 SMS_INIT_MSG(msg
, MSG_SW_RELOAD_START_REQ
,
496 sizeof(struct SmsMsgHdr_ST
));
497 rc
= smscore_sendrequest_and_wait(coredev
, msg
,
499 &coredev
->reload_start_done
);
500 mem_address
= *(u32
*) &payload
[20];
503 while (size
&& rc
>= 0) {
504 struct SmsDataDownload_ST
*DataMsg
=
505 (struct SmsDataDownload_ST
*) msg
;
506 int payload_size
= min((int) size
, SMS_MAX_PAYLOAD_SIZE
);
508 SMS_INIT_MSG(msg
, MSG_SMS_DATA_DOWNLOAD_REQ
,
509 (u16
)(sizeof(struct SmsMsgHdr_ST
) +
510 sizeof(u32
) + payload_size
));
512 DataMsg
->MemAddr
= mem_address
;
513 memcpy(DataMsg
->Payload
, payload
, payload_size
);
515 if ((coredev
->device_flags
& SMS_ROM_NO_RESPONSE
) &&
516 (coredev
->mode
== DEVICE_MODE_NONE
))
517 rc
= coredev
->sendrequest_handler(
518 coredev
->context
, DataMsg
,
519 DataMsg
->xMsgHeader
.msgLength
);
521 rc
= smscore_sendrequest_and_wait(
523 DataMsg
->xMsgHeader
.msgLength
,
524 &coredev
->data_download_done
);
526 payload
+= payload_size
;
527 size
-= payload_size
;
528 mem_address
+= payload_size
;
532 if (coredev
->mode
== DEVICE_MODE_NONE
) {
533 struct SmsMsgData_ST
*TriggerMsg
=
534 (struct SmsMsgData_ST
*) msg
;
536 SMS_INIT_MSG(msg
, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ
,
537 sizeof(struct SmsMsgHdr_ST
) +
540 TriggerMsg
->msgData
[0] = firmware
->StartAddress
;
542 TriggerMsg
->msgData
[1] = 5; /* Priority */
543 TriggerMsg
->msgData
[2] = 0x200; /* Stack size */
544 TriggerMsg
->msgData
[3] = 0; /* Parameter */
545 TriggerMsg
->msgData
[4] = 4; /* Task ID */
547 if (coredev
->device_flags
& SMS_ROM_NO_RESPONSE
) {
548 rc
= coredev
->sendrequest_handler(
549 coredev
->context
, TriggerMsg
,
550 TriggerMsg
->xMsgHeader
.msgLength
);
553 rc
= smscore_sendrequest_and_wait(
555 TriggerMsg
->xMsgHeader
.msgLength
,
556 &coredev
->trigger_done
);
558 SMS_INIT_MSG(msg
, MSG_SW_RELOAD_EXEC_REQ
,
559 sizeof(struct SmsMsgHdr_ST
));
561 rc
= coredev
->sendrequest_handler(coredev
->context
,
562 msg
, msg
->msgLength
);
567 sms_debug("rc=%d, postload=%p ", rc
,
568 coredev
->postload_handler
);
572 return ((rc
>= 0) && coredev
->postload_handler
) ?
573 coredev
->postload_handler(coredev
->context
) :
578 * loads specified firmware into a buffer and calls device loadfirmware_handler
580 * @param coredev pointer to a coredev object returned by
581 * smscore_register_device
582 * @param filename null-terminated string specifies firmware file name
583 * @param loadfirmware_handler device handler that loads firmware
585 * @return 0 on success, <0 on error.
587 static int smscore_load_firmware_from_file(struct smscore_device_t
*coredev
,
589 loadfirmware_t loadfirmware_handler
)
592 const struct firmware
*fw
;
595 if (loadfirmware_handler
== NULL
&& !(coredev
->device_flags
&
599 rc
= request_firmware(&fw
, filename
, coredev
->device
);
601 sms_info("failed to open \"%s\"", filename
);
604 sms_info("read FW %s, size=%zd", filename
, fw
->size
);
605 fw_buffer
= kmalloc(ALIGN(fw
->size
, SMS_ALLOC_ALIGNMENT
),
606 GFP_KERNEL
| GFP_DMA
);
608 memcpy(fw_buffer
, fw
->data
, fw
->size
);
610 rc
= (coredev
->device_flags
& SMS_DEVICE_FAMILY2
) ?
611 smscore_load_firmware_family2(coredev
,
614 loadfirmware_handler(coredev
->context
,
615 fw_buffer
, fw
->size
);
619 sms_info("failed to allocate firmware buffer");
623 release_firmware(fw
);
629 * notifies all clients registered with the device, notifies hotplugs,
630 * frees all buffers and coredev object
632 * @param coredev pointer to a coredev object returned by
633 * smscore_register_device
635 * @return 0 on success, <0 on error.
637 void smscore_unregister_device(struct smscore_device_t
*coredev
)
639 struct smscore_buffer_t
*cb
;
643 kmutex_lock(&g_smscore_deviceslock
);
645 smscore_notify_clients(coredev
);
646 smscore_notify_callbacks(coredev
, NULL
, 0);
648 /* at this point all buffers should be back
649 * onresponse must no longer be called */
652 while ((cb
= smscore_getbuffer(coredev
))) {
656 if (num_buffers
== coredev
->num_buffers
)
659 sms_info("exiting although "
660 "not all buffers released.");
664 sms_info("waiting for %d buffer(s)",
665 coredev
->num_buffers
- num_buffers
);
669 sms_info("freed %d buffers", num_buffers
);
671 if (coredev
->common_buffer
)
672 dma_free_coherent(NULL
, coredev
->common_buffer_size
,
673 coredev
->common_buffer
,
674 coredev
->common_buffer_phys
);
676 list_del(&coredev
->entry
);
679 kmutex_unlock(&g_smscore_deviceslock
);
681 sms_info("device %p destroyed", coredev
);
684 static int smscore_detect_mode(struct smscore_device_t
*coredev
)
686 void *buffer
= kmalloc(sizeof(struct SmsMsgHdr_ST
) + SMS_DMA_ALIGNMENT
,
687 GFP_KERNEL
| GFP_DMA
);
688 struct SmsMsgHdr_ST
*msg
=
689 (struct SmsMsgHdr_ST
*) SMS_ALIGN_ADDRESS(buffer
);
695 SMS_INIT_MSG(msg
, MSG_SMS_GET_VERSION_EX_REQ
,
696 sizeof(struct SmsMsgHdr_ST
));
698 rc
= smscore_sendrequest_and_wait(coredev
, msg
, msg
->msgLength
,
699 &coredev
->version_ex_done
);
701 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
703 if (wait_for_completion_timeout(&coredev
->resume_done
,
704 msecs_to_jiffies(5000))) {
705 rc
= smscore_sendrequest_and_wait(
706 coredev
, msg
, msg
->msgLength
,
707 &coredev
->version_ex_done
);
709 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
710 "second try, rc %d", rc
);
720 static char *smscore_fw_lkup
[][SMS_NUM_OF_DEVICE_TYPES
] = {
721 /*Stellar NOVA A0 Nova B0 VEGA*/
723 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
725 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
727 {"none", "tdmb_nova_12mhz.inp", "none", "none"},
729 {"none", "none", "none", "none"},
731 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
733 {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},
735 {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
737 {"none", "none", "none", "cmmb_vega_12mhz.inp"}
740 static inline char *sms_get_fw_name(struct smscore_device_t
*coredev
,
741 int mode
, enum sms_device_type_st type
)
743 char **fw
= sms_get_board(smscore_get_board_id(coredev
))->fw
;
744 return (fw
&& fw
[mode
]) ? fw
[mode
] : smscore_fw_lkup
[mode
][type
];
748 * calls device handler to change mode of operation
749 * NOTE: stellar/usb may disconnect when changing mode
751 * @param coredev pointer to a coredev object returned by
752 * smscore_register_device
753 * @param mode requested mode of operation
755 * @return 0 on success, <0 on error.
757 int smscore_set_device_mode(struct smscore_device_t
*coredev
, int mode
)
761 enum sms_device_type_st type
;
763 sms_debug("set device mode to %d", mode
);
764 if (coredev
->device_flags
& SMS_DEVICE_FAMILY2
) {
765 if (mode
< DEVICE_MODE_DVBT
|| mode
> DEVICE_MODE_RAW_TUNER
) {
766 sms_err("invalid mode specified %d", mode
);
770 smscore_registry_setmode(coredev
->devpath
, mode
);
772 if (!(coredev
->device_flags
& SMS_DEVICE_NOT_READY
)) {
773 rc
= smscore_detect_mode(coredev
);
775 sms_err("mode detect failed %d", rc
);
780 if (coredev
->mode
== mode
) {
781 sms_info("device mode %d already set", mode
);
785 if (!(coredev
->modes_supported
& (1 << mode
))) {
788 type
= smscore_registry_gettype(coredev
->devpath
);
789 fw_filename
= sms_get_fw_name(coredev
, mode
, type
);
791 rc
= smscore_load_firmware_from_file(coredev
,
794 sms_warn("error %d loading firmware: %s, "
795 "trying again with default firmware",
798 /* try again with the default firmware */
799 fw_filename
= smscore_fw_lkup
[mode
][type
];
800 rc
= smscore_load_firmware_from_file(coredev
,
804 sms_warn("error %d loading "
810 sms_log("firmware download success: %s", fw_filename
);
812 sms_info("mode %d supported by running "
815 buffer
= kmalloc(sizeof(struct SmsMsgData_ST
) +
816 SMS_DMA_ALIGNMENT
, GFP_KERNEL
| GFP_DMA
);
818 struct SmsMsgData_ST
*msg
=
819 (struct SmsMsgData_ST
*)
820 SMS_ALIGN_ADDRESS(buffer
);
822 SMS_INIT_MSG(&msg
->xMsgHeader
, MSG_SMS_INIT_DEVICE_REQ
,
823 sizeof(struct SmsMsgData_ST
));
824 msg
->msgData
[0] = mode
;
826 rc
= smscore_sendrequest_and_wait(
827 coredev
, msg
, msg
->xMsgHeader
.msgLength
,
828 &coredev
->init_device_done
);
832 sms_err("Could not allocate buffer for "
833 "init device message.");
837 if (mode
< DEVICE_MODE_DVBT
|| mode
> DEVICE_MODE_DVBT_BDA
) {
838 sms_err("invalid mode specified %d", mode
);
842 smscore_registry_setmode(coredev
->devpath
, mode
);
844 if (coredev
->detectmode_handler
)
845 coredev
->detectmode_handler(coredev
->context
,
848 if (coredev
->mode
!= mode
&& coredev
->setmode_handler
)
849 rc
= coredev
->setmode_handler(coredev
->context
, mode
);
853 coredev
->mode
= mode
;
854 coredev
->device_flags
&= ~SMS_DEVICE_NOT_READY
;
858 sms_err("return error code %d.", rc
);
863 * calls device handler to get current mode of operation
865 * @param coredev pointer to a coredev object returned by
866 * smscore_register_device
868 * @return current mode
870 int smscore_get_device_mode(struct smscore_device_t
*coredev
)
872 return coredev
->mode
;
876 * find client by response id & type within the clients list.
877 * return client handle or NULL.
879 * @param coredev pointer to a coredev object returned by
880 * smscore_register_device
881 * @param data_type client data type (SMS_DONT_CARE for all types)
882 * @param id client id (SMS_DONT_CARE for all id)
886 smscore_client_t
*smscore_find_client(struct smscore_device_t
*coredev
,
887 int data_type
, int id
)
889 struct smscore_client_t
*client
= NULL
;
890 struct list_head
*next
, *first
;
892 struct list_head
*firstid
, *nextid
;
895 spin_lock_irqsave(&coredev
->clientslock
, flags
);
896 first
= &coredev
->clients
;
897 for (next
= first
->next
;
898 (next
!= first
) && !client
;
900 firstid
= &((struct smscore_client_t
*)next
)->idlist
;
901 for (nextid
= firstid
->next
;
903 nextid
= nextid
->next
) {
904 if ((((struct smscore_idlist_t
*)nextid
)->id
== id
) &&
905 (((struct smscore_idlist_t
*)nextid
)->data_type
== data_type
||
906 (((struct smscore_idlist_t
*)nextid
)->data_type
== 0))) {
907 client
= (struct smscore_client_t
*) next
;
912 spin_unlock_irqrestore(&coredev
->clientslock
, flags
);
917 * find client by response id/type, call clients onresponse handler
918 * return buffer to pool on error
920 * @param coredev pointer to a coredev object returned by
921 * smscore_register_device
922 * @param cb pointer to response buffer descriptor
925 void smscore_onresponse(struct smscore_device_t
*coredev
,
926 struct smscore_buffer_t
*cb
)
928 struct SmsMsgHdr_ST
*phdr
=
929 (struct SmsMsgHdr_ST
*)((u8
*) cb
->p
+ cb
->offset
);
930 struct smscore_client_t
*client
=
931 smscore_find_client(coredev
, phdr
->msgType
, phdr
->msgDstId
);
934 static unsigned long last_sample_time
; /* = 0; */
935 static int data_total
; /* = 0; */
936 unsigned long time_now
= jiffies_to_msecs(jiffies
);
938 if (!last_sample_time
)
939 last_sample_time
= time_now
;
941 if (time_now
- last_sample_time
> 10000) {
942 sms_debug("\ndata rate %d bytes/secs",
943 (int)((data_total
* 1000) /
944 (time_now
- last_sample_time
)));
946 last_sample_time
= time_now
;
950 data_total
+= cb
->size
;
951 /* If no client registered for type & id,
952 * check for control client where type is not registered */
954 rc
= client
->onresponse_handler(client
->context
, cb
);
957 switch (phdr
->msgType
) {
958 case MSG_SMS_GET_VERSION_EX_RES
:
960 struct SmsVersionRes_ST
*ver
=
961 (struct SmsVersionRes_ST
*) phdr
;
962 sms_debug("MSG_SMS_GET_VERSION_EX_RES "
963 "id %d prots 0x%x ver %d.%d",
964 ver
->FirmwareId
, ver
->SupportedProtocols
,
965 ver
->RomVersionMajor
, ver
->RomVersionMinor
);
967 coredev
->mode
= ver
->FirmwareId
== 255 ?
968 DEVICE_MODE_NONE
: ver
->FirmwareId
;
969 coredev
->modes_supported
= ver
->SupportedProtocols
;
971 complete(&coredev
->version_ex_done
);
974 case MSG_SMS_INIT_DEVICE_RES
:
975 sms_debug("MSG_SMS_INIT_DEVICE_RES");
976 complete(&coredev
->init_device_done
);
978 case MSG_SW_RELOAD_START_RES
:
979 sms_debug("MSG_SW_RELOAD_START_RES");
980 complete(&coredev
->reload_start_done
);
982 case MSG_SMS_DATA_DOWNLOAD_RES
:
983 complete(&coredev
->data_download_done
);
985 case MSG_SW_RELOAD_EXEC_RES
:
986 sms_debug("MSG_SW_RELOAD_EXEC_RES");
988 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES
:
989 sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
990 complete(&coredev
->trigger_done
);
992 case MSG_SMS_SLEEP_RESUME_COMP_IND
:
993 complete(&coredev
->resume_done
);
998 smscore_putbuffer(coredev
, cb
);
1003 * return pointer to next free buffer descriptor from core pool
1005 * @param coredev pointer to a coredev object returned by
1006 * smscore_register_device
1008 * @return pointer to descriptor on success, NULL on error.
1010 struct smscore_buffer_t
*smscore_getbuffer(struct smscore_device_t
*coredev
)
1012 struct smscore_buffer_t
*cb
= NULL
;
1013 unsigned long flags
;
1015 spin_lock_irqsave(&coredev
->bufferslock
, flags
);
1017 if (!list_empty(&coredev
->buffers
)) {
1018 cb
= (struct smscore_buffer_t
*) coredev
->buffers
.next
;
1019 list_del(&cb
->entry
);
1022 spin_unlock_irqrestore(&coredev
->bufferslock
, flags
);
1028 * return buffer descriptor to a pool
1030 * @param coredev pointer to a coredev object returned by
1031 * smscore_register_device
1032 * @param cb pointer buffer descriptor
1035 void smscore_putbuffer(struct smscore_device_t
*coredev
,
1036 struct smscore_buffer_t
*cb
)
1038 list_add_locked(&cb
->entry
, &coredev
->buffers
, &coredev
->bufferslock
);
1041 static int smscore_validate_client(struct smscore_device_t
*coredev
,
1042 struct smscore_client_t
*client
,
1043 int data_type
, int id
)
1045 struct smscore_idlist_t
*listentry
;
1046 struct smscore_client_t
*registered_client
;
1049 sms_err("bad parameter.");
1052 registered_client
= smscore_find_client(coredev
, data_type
, id
);
1053 if (registered_client
== client
)
1056 if (registered_client
) {
1057 sms_err("The msg ID already registered to another client.");
1060 listentry
= kzalloc(sizeof(struct smscore_idlist_t
), GFP_KERNEL
);
1062 sms_err("Can't allocate memory for client id.");
1066 listentry
->data_type
= data_type
;
1067 list_add_locked(&listentry
->entry
, &client
->idlist
,
1068 &coredev
->clientslock
);
1073 * creates smsclient object, check that id is taken by another client
1075 * @param coredev pointer to a coredev object from clients hotplug
1076 * @param initial_id all messages with this id would be sent to this client
1077 * @param data_type all messages of this type would be sent to this client
1078 * @param onresponse_handler client handler that is called to
1079 * process incoming messages
1080 * @param onremove_handler client handler that is called when device is removed
1081 * @param context client-specific context
1082 * @param client pointer to a value that receives created smsclient object
1084 * @return 0 on success, <0 on error.
1086 int smscore_register_client(struct smscore_device_t
*coredev
,
1087 struct smsclient_params_t
*params
,
1088 struct smscore_client_t
**client
)
1090 struct smscore_client_t
*newclient
;
1091 /* check that no other channel with same parameters exists */
1092 if (smscore_find_client(coredev
, params
->data_type
,
1093 params
->initial_id
)) {
1094 sms_err("Client already exist.");
1098 newclient
= kzalloc(sizeof(struct smscore_client_t
), GFP_KERNEL
);
1100 sms_err("Failed to allocate memory for client.");
1104 INIT_LIST_HEAD(&newclient
->idlist
);
1105 newclient
->coredev
= coredev
;
1106 newclient
->onresponse_handler
= params
->onresponse_handler
;
1107 newclient
->onremove_handler
= params
->onremove_handler
;
1108 newclient
->context
= params
->context
;
1109 list_add_locked(&newclient
->entry
, &coredev
->clients
,
1110 &coredev
->clientslock
);
1111 smscore_validate_client(coredev
, newclient
, params
->data_type
,
1112 params
->initial_id
);
1113 *client
= newclient
;
1114 sms_debug("%p %d %d", params
->context
, params
->data_type
,
1115 params
->initial_id
);
1121 * frees smsclient object and all subclients associated with it
1123 * @param client pointer to smsclient object returned by
1124 * smscore_register_client
1127 void smscore_unregister_client(struct smscore_client_t
*client
)
1129 struct smscore_device_t
*coredev
= client
->coredev
;
1130 unsigned long flags
;
1132 spin_lock_irqsave(&coredev
->clientslock
, flags
);
1135 while (!list_empty(&client
->idlist
)) {
1136 struct smscore_idlist_t
*identry
=
1137 (struct smscore_idlist_t
*) client
->idlist
.next
;
1138 list_del(&identry
->entry
);
1142 sms_info("%p", client
->context
);
1144 list_del(&client
->entry
);
1147 spin_unlock_irqrestore(&coredev
->clientslock
, flags
);
1151 * verifies that source id is not taken by another client,
1152 * calls device handler to send requests to the device
1154 * @param client pointer to smsclient object returned by
1155 * smscore_register_client
1156 * @param buffer pointer to a request buffer
1157 * @param size size (in bytes) of request buffer
1159 * @return 0 on success, <0 on error.
1161 int smsclient_sendrequest(struct smscore_client_t
*client
,
1162 void *buffer
, size_t size
)
1164 struct smscore_device_t
*coredev
;
1165 struct SmsMsgHdr_ST
*phdr
= (struct SmsMsgHdr_ST
*) buffer
;
1168 if (client
== NULL
) {
1169 sms_err("Got NULL client");
1173 coredev
= client
->coredev
;
1175 /* check that no other channel with same id exists */
1176 if (coredev
== NULL
) {
1177 sms_err("Got NULL coredev");
1181 rc
= smscore_validate_client(client
->coredev
, client
, 0,
1186 return coredev
->sendrequest_handler(coredev
->context
, buffer
, size
);
1190 static int __init
smscore_module_init(void)
1194 INIT_LIST_HEAD(&g_smscore_notifyees
);
1195 INIT_LIST_HEAD(&g_smscore_devices
);
1196 kmutex_init(&g_smscore_deviceslock
);
1198 INIT_LIST_HEAD(&g_smscore_registry
);
1199 kmutex_init(&g_smscore_registrylock
);
1202 rc
= smsusb_register();
1205 rc
= smsdvb_register();
1207 sms_debug("rc %d", rc
);
1212 static void __exit
smscore_module_exit(void)
1215 kmutex_lock(&g_smscore_deviceslock
);
1216 while (!list_empty(&g_smscore_notifyees
)) {
1217 struct smscore_device_notifyee_t
*notifyee
=
1218 (struct smscore_device_notifyee_t
*)
1219 g_smscore_notifyees
.next
;
1221 list_del(¬ifyee
->entry
);
1224 kmutex_unlock(&g_smscore_deviceslock
);
1226 kmutex_lock(&g_smscore_registrylock
);
1227 while (!list_empty(&g_smscore_registry
)) {
1228 struct smscore_registry_entry_t
*entry
=
1229 (struct smscore_registry_entry_t
*)
1230 g_smscore_registry
.next
;
1232 list_del(&entry
->entry
);
1235 kmutex_unlock(&g_smscore_registrylock
);
1237 /* DVB UnRegister */
1238 smsdvb_unregister();
1240 /* Unregister USB */
1241 smsusb_unregister();
1246 module_init(smscore_module_init
);
1247 module_exit(smscore_module_exit
);
1249 MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
1250 MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
1251 MODULE_LICENSE("GPL");