source: svn/trunk/newcon3bcm2_21bu/dta/src/settop_api/bsettop_smartcard.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 16.3 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2009-2010, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile:  $
11 * $brcm_Revision:  $
12 * $brcm_Date:  $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log:  $
19 *
20 ***************************************************************************/
21#include "bsettop_smartcard.h"
22#include "bstd.h"
23#include "bscd.h"
24#include "gist.h"
25
26BDBG_MODULE(smartcard);
27
28bresult bscd_settop_err(const char* func,int line,char *err_str,bresult err);
29#define BSETTOP_ERROR(x)        bscd_settop_err(__FUNCTION__,__LINE__,#x,x)
30#define B_ID_IS_INDEX(x)        (x == 0)
31
32/*
33 * error debugging function
34 */
35bresult bscd_settop_err(const char* func,int line,char *err_str,bresult err)
36{
37        BDBG_ERR(("%s:%d - %s\n",func,line,err_str));
38        return err;
39}
40
41static b_task_t bsmartcard_task_h;
42typedef struct bsmartcard_event_t
43{
44        b_queue_t       queue;
45        b_event_t       events[4];
46}bsmartcard_event_t;
47static bsmartcard_event_t s_bsmartcard_event;
48
49struct bsmartcard
50{
51        BSCD_ChannelHandle channelHandle; /* scd channel */ 
52        BSCD_ChannelSettings channelSettings;
53        bsmartcard_settings_t settings;
54        bsmartcard_state state;
55        unsigned int *p_stack;
56} ;
57
58struct scd_module
59{
60        BSCD_Handle moduleHandle;
61        BSCD_Settings moduleSettings;
62        struct bsmartcard cliChannel[BSCD_MAX_SUPPOTED_CHANNELS];   
63        bool card_inserted[BSCD_MAX_SUPPOTED_CHANNELS];
64        bool card_removed[BSCD_MAX_SUPPOTED_CHANNELS];
65        bool done;
66} g_smartcard;
67
68
69static bresult bsmartcard_p_set_settings(
70                                                                                BSCD_ChannelSettings    *inoutp_sSettings,
71                                                                                bsmartcard_standard     standard,
72                                                                                bsmartcard_protocol     protocol
73                                                                                );
74
75static void bsmartcard_p_card_inserted( BSCD_ChannelHandle in_channelHandle, void * inp_data ) {
76        int i;
77
78        /* Sadly, there does not currently appear to be a means of setting inp_data to the specific bsmartcard. */
79        BSTD_UNUSED(inp_data);
80        BDBG_MSG(("Card insertion detected."));
81        for (i=0; i < BSCD_MAX_SUPPOTED_CHANNELS; i++)
82        {
83                if (g_smartcard.cliChannel[i].channelHandle == in_channelHandle)
84                {
85                        g_smartcard.card_inserted[i] = 1;
86                }
87        }
88        bos_post_event(s_bsmartcard_event.queue,(b_event_t*)(s_bsmartcard_event.events));   
89}
90
91static void bsmartcard_p_card_removed( BSCD_ChannelHandle in_channelHandle, void * inp_data ) {
92        int i;
93
94        /* Sadly, there does not currently appear to be a means of setting inp_data to the specific bsmartcard. */
95        BSTD_UNUSED(inp_data);
96        BDBG_MSG(("Card removal detected"));
97        for (i=0; i < BSCD_MAX_SUPPOTED_CHANNELS; i++)
98        {
99                if (g_smartcard.cliChannel[i].channelHandle == in_channelHandle)
100                {
101                        g_smartcard.card_removed[i] = 1;
102                }
103        }
104        bos_post_event(s_bsmartcard_event.queue,(b_event_t*)(s_bsmartcard_event.events));   
105}
106
107bresult
108bsmartcard_init(void)
109{
110        BERR_Code rc;
111
112        rc = BSCD_GetDefaultSettings(&g_smartcard.moduleSettings, GetCHP());
113        if (rc!=BERR_SUCCESS)
114        {
115                return BSETTOP_ERROR(berr_external_error);
116        }
117
118        g_smartcard.done = false;
119        g_smartcard.moduleSettings.moduleClkFreq.FreqSrc = BSCD_ClockFreqSrc_eInternalClock;
120        g_smartcard.moduleSettings.moduleClkFreq.ulClkFreq = 27000000;
121        g_smartcard.moduleSettings.ucMaxChannels = BSCD_MAX_SUPPOTED_CHANNELS;
122
123        g_smartcard.card_inserted[0] = 0;
124        g_smartcard.card_inserted[1] = 0;
125        g_smartcard.card_removed[0] = 0;
126        g_smartcard.card_removed[1] = 0;
127
128        rc = BSCD_Open(&g_smartcard.moduleHandle, GetREG(), GetCHP(), 
129                                   GetINT(), &g_smartcard.moduleSettings);
130        if (rc!=BERR_SUCCESS)
131        {
132                return BSETTOP_ERROR(berr_external_error);
133        }
134
135        bos_create_queue(&s_bsmartcard_event.queue, s_bsmartcard_event.events, 4);
136
137        return b_ok;
138}
139
140
141void
142bsmartcard_shutdown(void)
143{
144        BSCD_Close(g_smartcard.moduleHandle);
145        return;
146}
147
148void bsmartcard_settings_init(bsmartcard_settings_t *settings)
149{
150        BDBG_ASSERT(settings);
151
152        BKNI_Memset(settings,0,sizeof(*settings));
153        /* these match the old hard-coded values */
154        settings->protocol = bsmartcard_protocol_t0;
155        settings->standard = bsmartcard_standard_nds;
156        settings->callback_context = NULL;
157        settings->card_insertion = NULL;
158        settings->card_removal = NULL;
159}
160
161static void bsmardcard_task(void *data)
162{
163        int i;
164        while (!g_smartcard.done)
165        {
166                bos_pend_event(s_bsmartcard_event.queue, 0xFF);
167                for (i=0; i < BSCD_MAX_SUPPOTED_CHANNELS; i++)
168                {
169                        if (g_smartcard.card_inserted[i])
170                        {
171                                if (g_smartcard.cliChannel[i].settings.card_insertion)
172                                {
173                                        g_smartcard.cliChannel[i].settings.card_insertion(g_smartcard.cliChannel[i].settings.callback_context);
174                                }
175                                g_smartcard.card_inserted[i] = 0;
176                        }
177                        if (g_smartcard.card_removed[i])
178                        {
179                                if (g_smartcard.cliChannel[i].settings.card_removal)
180                                {
181                                        g_smartcard.cliChannel[i].settings.card_removal(g_smartcard.cliChannel[i].settings.callback_context);
182                                }
183                                g_smartcard.card_removed[i] = 0;
184                        }
185                }
186        }
187}
188
189bsmartcard_t bsmartcard_open(bobject_t smartcard_id, bsmartcard_t * smartcard, const bsmartcard_settings_t *settings)
190{
191        BERR_Code rc;
192        unsigned int index;
193        b_task_params params;
194        b_task_t task_h;
195
196        BDBG_ASSERT(settings);
197
198        if (B_ID_IS_INDEX(smartcard_id))
199        {
200                index = B_ID_GET_INDEX(smartcard_id);
201        }
202        else
203        {
204                if (smartcard_id==0)
205                {
206                        BSETTOP_ERROR(berr_invalid_parameter);
207                        goto error;
208                }
209                BSETTOP_ERROR(berr_not_available);
210                goto error;
211        }
212        if (index >= BSCD_MAX_SUPPOTED_CHANNELS)
213        {
214                BSETTOP_ERROR(berr_invalid_parameter);
215                goto error;
216        }
217        g_smartcard.cliChannel[index].p_stack = BKNI_Malloc(256*4);
218        if (!(g_smartcard.cliChannel[index].p_stack))
219        {
220                BSETTOP_ERROR(berr_out_of_memory);
221                goto error;
222        }
223
224        g_smartcard.cliChannel[index].state = bsmartcard_state_unknown;
225        g_smartcard.cliChannel[index].settings = *settings;
226
227        rc = BSCD_GetChannelDefaultSettings(g_smartcard.moduleHandle, index, 
228                                                                                &g_smartcard.cliChannel[index].channelSettings);
229        if (rc!=BERR_SUCCESS)
230        {
231                BSETTOP_ERROR(berr_external_error);
232                goto error;
233        }
234
235        if (settings->standard == bsmartcard_standard_nds || settings->standard == bsmartcard_standard_iso)
236        {
237                if (bsmartcard_p_set_settings(&g_smartcard.cliChannel[index].channelSettings, settings->standard, settings->protocol) != b_ok)
238                {
239                        BSETTOP_ERROR(berr_external_error);
240                        goto error;     
241                }
242        }
243        else
244        {
245                BDBG_ERR(("The requested standard is not supported at this time"));
246                BSETTOP_ERROR(berr_not_available);
247        }
248
249        rc = BSCD_Channel_Open(g_smartcard.moduleHandle, &g_smartcard.cliChannel[index].channelHandle, 
250                                                   index, &g_smartcard.cliChannel[index].channelSettings);
251        if (rc!=BERR_SUCCESS)
252        {
253                BSETTOP_ERROR(berr_external_error);
254                goto error;
255        }
256
257        BSCD_Channel_EnableIntrCallback_isr(g_smartcard.cliChannel[index].channelHandle,BSCD_IntType_eCardInsertInt,bsmartcard_p_card_inserted);
258        BSCD_Channel_EnableIntrCallback_isr(g_smartcard.cliChannel[index].channelHandle,BSCD_IntType_eCardRemoveInt,bsmartcard_p_card_removed);
259
260        *smartcard = &g_smartcard.cliChannel[index];
261        params.name="smartcard_task";
262        params.priority = 8;
263        params.stack_size = 256;
264        params.stack = g_smartcard.cliChannel[index].p_stack;
265        bos_start_task(&task_h,&params, bsmardcard_task, &task_h);
266        if (!task_h)
267        {
268                BDBG_ERR(("task_h create failed\n"));
269        }
270        bsmartcard_task_h = task_h;
271
272        return *smartcard;
273
274        error:
275        *smartcard = NULL;
276        return *smartcard;
277}
278
279void bsmartcard_close(bsmartcard_t smartcard)
280{
281        BDBG_ASSERT(smartcard);
282
283        smartcard->state = bsmartcard_state_unknown;
284        if (BSCD_Channel_Close(smartcard->channelHandle) != b_ok)
285                BSETTOP_ERROR(berr_external_error);
286        bos_stop_task(bsmartcard_task_h);
287        bos_delete_queue(&s_bsmartcard_event.queue);
288        if (smartcard->p_stack)
289        {
290                BKNI_Free(smartcard->p_stack);
291                smartcard->p_stack = NULL;
292        }
293
294}
295
296bresult bsmartcard_reset(bsmartcard_t smartcard, bool warm_reset)
297{
298        BDBG_ASSERT(smartcard);
299
300        smartcard->state = warm_reset ? bsmartcard_state_warm_resetting : bsmartcard_state_cold_resetting;
301        if (BSCD_Channel_ResetIFD(smartcard->channelHandle, warm_reset ? BSCD_ResetType_eWarm : BSCD_ResetType_eCold))
302        {
303                smartcard->state = bsmartcard_state_reset_done;
304                return BSETTOP_ERROR(berr_external_error);
305        }
306        smartcard->state = bsmartcard_state_reset_done;
307        return b_ok;
308}
309
310
311bresult bsmartcard_read(bsmartcard_t smartcard, void *data,
312                                                size_t length, size_t *length_read)
313{
314        BDBG_ASSERT(smartcard);
315
316        smartcard->state = bsmartcard_state_receiving;
317        if (BSCD_Channel_Receive(smartcard->channelHandle,
318                                                         data, (unsigned long *) length_read, length) != b_ok)
319        {
320                smartcard->state = bsmartcard_state_ready;
321                return BSETTOP_ERROR(berr_external_error);
322        }
323
324        smartcard->state = bsmartcard_state_ready;
325        if (*length_read <= 0)
326        {
327                return BSETTOP_ERROR(berr_external_error);;
328        }
329
330        return b_ok;
331}
332
333bresult bsmartcard_write(bsmartcard_t smartcard, const void *data,
334                                                 size_t length, size_t *length_written)
335{
336        BDBG_ASSERT(smartcard);
337
338        smartcard->state = bsmartcard_state_transmitting;
339
340        if (BSCD_Channel_Transmit(  smartcard->channelHandle,   (uint8_t *) data, length) != b_ok)
341        {
342                *length_written = 0;
343                smartcard->state = bsmartcard_state_transmitted;
344                return BSETTOP_ERROR(berr_external_error);;     
345        }
346        else
347        {
348                *length_written = length;
349                smartcard->state = bsmartcard_state_transmitted;
350                return b_ok;
351        }
352}
353
354bresult bsmartcard_get_status(bsmartcard_t smartcard, bsmartcard_status *status)
355{
356
357        BSCD_Status                 internal_status;
358
359        BDBG_ASSERT(smartcard);
360
361        if (BSCD_Channel_GetStatus(smartcard->channelHandle, &internal_status) != b_ok)
362        {
363                return BSETTOP_ERROR(berr_external_error);
364        }
365        status->err = bsmartcard_no_error;
366        status->card_present = internal_status.bCardPresent;
367        status->state = smartcard->state;
368        return b_ok;
369}
370
371bresult bsmartcard_detect_card(bsmartcard_t smartcard)
372{
373        BDBG_ASSERT(smartcard);
374
375        if (BSCD_Channel_DetectCard(smartcard->channelHandle, BSCD_CardPresent_eInserted) != b_ok)
376        {
377                return BSETTOP_ERROR(berr_external_error);
378        }
379        return b_ok;
380}
381
382bresult bsmartcard_reset_card(bsmartcard_t smartcard,
383                                                          void *data, size_t length, size_t *length_read)
384{
385        BDBG_ASSERT(smartcard);
386
387        smartcard->state = bsmartcard_state_unknown;
388
389        if (BSCD_Channel_ResetCard(smartcard->channelHandle, BSCD_ResetCardAction_eNoAction) != b_ok)
390        {
391                return BSETTOP_ERROR(berr_external_error);
392        }
393
394        if (data)
395        {
396                if (BSCD_Channel_Receive(smartcard->channelHandle,
397                                                                 data, (unsigned long *) length_read, length) != b_ok)
398                        return BSETTOP_ERROR(berr_external_error);
399
400                if (*length_read > length)
401                {
402                        return BSETTOP_ERROR(berr_invalid_parameter);
403                }
404                if (*length_read <= 0)
405                {
406                        return BSETTOP_ERROR(berr_external_error);
407                }
408                else
409                {
410                        smartcard->state = bsmartcard_state_reset_done;
411                        /* interpret ATR data and set the settings */
412                        smartcard->channelSettings.extraGuardTime.ulValue = ((unsigned long *) data )[4];
413                        return b_ok;
414                }
415        }
416        return BSETTOP_ERROR(berr_external_error);
417}
418
419bresult bsmartcard_set_params_from_atr (
420                                                                           bsmartcard_t smartcard
421                                                                           )
422{
423        BDBG_ASSERT(smartcard);
424
425        smartcard->state = bsmartcard_state_receive_decode_atr;
426        if (BSCD_Channel_SetParameters(smartcard->channelHandle,
427                                                                   &(smartcard->channelSettings)) != b_ok)
428        {
429                smartcard->state = bsmartcard_state_unknown;
430                return BSETTOP_ERROR(berr_external_error);
431        }
432
433        if (BSCD_Channel_EnableInterrupts(smartcard->channelHandle)  != b_ok)
434        {
435                smartcard->state = bsmartcard_state_unknown;
436                return BSETTOP_ERROR(berr_external_error);
437        }
438
439        smartcard->state = bsmartcard_state_ready;
440        return b_ok;
441}
442
443static bresult bsmartcard_p_set_settings(
444                                                                                BSCD_ChannelSettings    *inoutp_sSettings,
445                                                                                bsmartcard_standard     standard,
446                                                                                bsmartcard_protocol     protocol
447                                                                                )
448{
449        /*  Smart Card Standard */
450        switch (standard)
451        {
452        case bsmartcard_standard_nds:
453                inoutp_sSettings->scStandard = BSCD_Standard_eNDS;
454                break;
455        case bsmartcard_standard_iso:
456                inoutp_sSettings->scStandard = BSCD_Standard_eISO;
457                break;
458        default:
459                inoutp_sSettings->scStandard = BSCD_Standard_eUnknown;
460                break;
461        }
462
463        /* Asynchronous Protocol Types. */
464        switch (protocol)
465        {
466        case bsmartcard_protocol_t1:
467                inoutp_sSettings->eProtocolType = BSCD_AsyncProtocolType_e1;
468                break;
469        case bsmartcard_protocol_t14:
470                inoutp_sSettings->eProtocolType = BSCD_AsyncProtocolType_e14_IRDETO;
471                break;
472        case bsmartcard_protocol_t0:
473        default:
474                inoutp_sSettings->eProtocolType = BSCD_AsyncProtocolType_e0;
475                break;
476        }
477
478        /* Set F,       Clock Rate Conversion Factor */
479        inoutp_sSettings->ucFFactor = 1;
480
481        /* Set D,       Baud Rate Adjustor */
482        inoutp_sSettings->ucDFactor = 1;   
483
484        /* Set ETU Clock Divider */ 
485        inoutp_sSettings->ucEtuClkDiv = 6;     
486
487        /* Set SC Clock Divider */ 
488        inoutp_sSettings->ucScClkDiv = 1;       
489
490        /* Set external Clock Divisor.  For TDA only 1, 2,4,8 are valid value. */ 
491        inoutp_sSettings->ucExternalClockDivisor = 1;   
492
493        /* Set Prescale */ 
494        inoutp_sSettings->unPrescale = 0x0B;
495
496        /* Set baud divisor */
497        inoutp_sSettings->ucBaudDiv = 0x1F; 
498
499        /* Set ICC CLK Freq */     
500
501
502        /* If the final ISO baudrate is not equal to the final BRCM baudrate, there is a potential mismatch */
503
504
505        /* Set maximum IFSD */
506
507        /* Set current IFSD */
508        inoutp_sSettings->unCurrentIFSD = BSCD_MAX_TX_SIZE; 
509
510        /* Set Number of transmit parity retries */
511        inoutp_sSettings->ucTxRetries = 4;     
512
513        /* Set Number of receive parity retries */
514        inoutp_sSettings->ucRxRetries = 4;     
515
516        /* Set work waiting time */
517        inoutp_sSettings->workWaitTime.ulValue =  BSCD_DEFAULT_WORK_WAITING_TIME ;     
518        inoutp_sSettings->workWaitTime.unit = BSCD_TimerUnit_eETU; 
519
520        /* Set block Wait time */
521        inoutp_sSettings->blockWaitTime.ulValue =  BSCD_DEFAULT_BLOCK_WAITING_TIME ;       
522        inoutp_sSettings->blockWaitTime.unit = BSCD_TimerUnit_eETU; 
523
524        /* Set Extra Guard Time  */
525        inoutp_sSettings->extraGuardTime.ulValue =  BSCD_DEFAULT_EXTRA_GUARD_TIME ;     
526        inoutp_sSettings->extraGuardTime.unit = BSCD_TimerUnit_eETU;   
527
528        /* Set block Guard time */
529        inoutp_sSettings->blockGuardTime.ulValue =  BSCD_DEFAULT_BLOCK_GUARD_TIME ;     
530        inoutp_sSettings->blockGuardTime.unit = BSCD_TimerUnit_eETU;   
531
532        /* Set character Wait time Integer */
533        inoutp_sSettings->ulCharacterWaitTimeInteger =  BSCD_DEFAULT_CHARACTER_WAIT_TIME_INTEGER ;     
534
535        /* Set EDC encoding */
536        inoutp_sSettings->edcSetting.bIsEnabled = false;       
537
538        /* Set transaction time out */
539        inoutp_sSettings->timeOut.ulValue =  BSCD_DEFAULT_TIME_OUT ;       
540        inoutp_sSettings->timeOut.unit = BSCD_TimerUnit_eMilliSec; 
541
542        /* auto deactivation sequence */
543        inoutp_sSettings->bAutoDeactiveReq =  false;   
544
545        /* nullFilter */
546        inoutp_sSettings->bNullFilter = false; 
547
548        /* debounce info */
549        inoutp_sSettings->scPresDbInfo.bIsEnabled = false;      /* Use TDA chip */
550        inoutp_sSettings->scPresDbInfo.ucDbWidth = BSCD_DEFAULT_DB_WIDTH;
551        inoutp_sSettings->scPresDbInfo.scPresMode = BSCD_ScPresMode_eMask;
552
553        /* Specify if we want the driver to read, decode and program registers */                       
554        inoutp_sSettings->resetCardAction = BSCD_ResetCardAction_eNoAction;
555
556        return b_ok ;
557}
558
559#ifdef CONFIG_SMARTCARD_TEST
560#include "ministd.h"
561void bsettop_smartcard_test(void)
562{
563        int cnt = 0;
564        bsmartcard_settings_t settings;
565        bsmartcard_t smartcard;
566
567        bsmartcard_init();
568        bsmartcard_settings_init(&settings);
569        smartcard = bsmartcard_open(0,&smartcard,&settings);
570        bsmartcard_reset(smartcard,false);
571
572        while (cnt++ < 120)
573        {
574                printf("Check for smartcard...\n");
575                if (bsmartcard_detect_card(smartcard) == b_ok)
576                {
577#define MAX_ATR_LEN 256
578                        size_t atr_len = MAX_ATR_LEN;
579                        static char *atr_buffer[MAX_ATR_LEN+1];
580                        printf("Smartcard detected\n");
581
582                        /* Must reset interface again and detect card again */
583                        printf("Reset smartcard interface... \n");
584                        bsmartcard_reset(smartcard,false);
585                        if (bsmartcard_detect_card(smartcard) != b_ok)
586                        {
587                                printf("Reset smartcard interface failed... \n");
588                                continue;
589                        }
590
591                        printf("Smartcard reset card\n");
592                        if (bsmartcard_reset_card(smartcard,atr_buffer,atr_len,&atr_len) != b_ok)
593                        {
594                                printf("Smartcard reset card failed\n");
595                                continue;
596                        }
597                       
598                        if (atr_len > 0)
599                        {
600                                atr_buffer[atr_len] = 0;
601                                printf("Smartcard reset card ATR %d bytes = %s\n",atr_len,atr_buffer);
602                                if (bsmartcard_set_params_from_atr(smartcard) != b_ok)
603                                {
604                                        printf("Smartcard bsmartcard_set_params_from_atr failed\n");
605                                        continue;
606                                }
607                                break;
608                        }
609                        else
610                        {
611                                printf("Smartcard reset card failed. ATR length = 0\n");
612                        }
613                }
614                else
615                        printf("No smartcard detected\n");
616
617                bos_sleep(1000);
618        }
619        bsmartcard_close(smartcard);
620        bsmartcard_shutdown();
621}
622
623#endif /* CONFIG_SMARTCARD_TEST */
Note: See TracBrowser for help on using the repository browser.