source: trunk/reader-common.c @ 5375

Last change on this file since 5375 was 5299, checked in by Admin, 8 years ago

Replace all malloc/calloc calls (in main OSCam directory) with cs_malloc and add handling for memory allocation failures.

File size: 10.1 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3#include "defines.h"
4#include "atr.h"
5#include "icc_async_exports.h"
6#ifdef AZBOX
7#include "csctapi/ifd_azbox.h"
8#endif
9
10#if defined(TUXBOX) && defined(PPC) //dbox2 only
11#include "csctapi/mc_global.h"
12static int32_t reader_device_type(struct s_reader * reader)
13{
14  int32_t rc=reader->typ;
15  struct stat sb;
16  if (reader->typ == R_MOUSE)
17  {
18      if (!stat(reader->device, &sb))
19      {
20        if (S_ISCHR(sb.st_mode))
21        {
22          int32_t dev_major, dev_minor;
23          dev_major=major(sb.st_rdev);
24          dev_minor=minor(sb.st_rdev);
25          if (((dev_major==4) || (dev_major==5)))
26            switch(dev_minor & 0x3F)
27            {
28              case 0: rc=R_DB2COM1; break;
29              case 1: rc=R_DB2COM2; break;
30            }
31          cs_debug_mask(D_READER, "device is major: %d, minor: %d, typ=%d", dev_major, dev_minor, rc);
32        }
33      }
34  }
35    reader->typ = rc;
36  return(rc);
37}
38#endif
39
40static void reader_nullcard(struct s_reader * reader)
41{
42  reader->csystem.active=0;
43  memset(reader->hexserial, 0   , sizeof(reader->hexserial));
44  memset(reader->prid     , 0xFF, sizeof(reader->prid     ));
45  reader->caid=0;
46  memset(reader->availkeys, 0   , sizeof(reader->availkeys));
47  reader->acs=0;
48  reader->nprov=0;
49}
50
51int32_t reader_cmd2icc(struct s_reader * reader, const uchar *buf, const int32_t l, uchar * cta_res, uint16_t * p_cta_lr)
52{
53    int32_t rc;
54    *p_cta_lr=CTA_RES_LEN-1; //FIXME not sure whether this one is necessary
55    cs_ddump_mask(D_READER, buf, l, "write to cardreader %s:",reader->label);
56    rc=ICC_Async_CardWrite(reader, (uchar *)buf, (uint16_t)l, cta_res, p_cta_lr);
57    return rc;
58}
59
60#define CMD_LEN 5
61
62int32_t card_write(struct s_reader * reader, const uchar *cmd, const uchar *data, uchar *response, uint16_t * response_length)
63{
64  uchar buf[260];
65  // always copy to be able to be able to use const buffer without changing all code 
66  memcpy(buf, cmd, CMD_LEN); 
67
68  if (data) {
69    if (cmd[4]) memcpy(buf+CMD_LEN, data, cmd[4]);
70    return(reader_cmd2icc(reader, buf, CMD_LEN+cmd[4], response, response_length));
71  }
72  else
73    return(reader_cmd2icc(reader, buf, CMD_LEN, response, response_length));
74}
75
76int32_t check_sct_len(const uchar *data, int32_t off)
77{
78    int32_t l = SCT_LEN(data);
79    if (l+off > MAX_LEN) {
80        cs_debug_mask(D_READER, "check_sct_len(): smartcard section too long %d > %d", l, MAX_LEN-off);
81        l = -1;
82    }
83    return(l);
84}
85
86
87static int32_t reader_card_inserted(struct s_reader * reader)
88{
89#ifndef USE_GPIO
90    if ((reader->detect&0x7f) > 3)
91        return 1;
92#endif
93    int32_t card;
94    if (ICC_Async_GetStatus (reader, &card)) {
95        cs_log("Error getting status of terminal.");
96        return 0; //corresponds with no card inside!!
97    }
98    return (card);
99}
100
101static int32_t reader_activate_card(struct s_reader * reader, ATR * atr, uint16_t deprecated)
102{
103  int32_t i,ret;
104    if (!reader_card_inserted(reader))
105        return 0;
106
107  /* Activate card */
108  for (i=0; i<3; i++) {
109        ret = ICC_Async_Activate(reader, atr, deprecated);
110        if (!ret)
111            break;
112        cs_log("Error activating card.");
113#ifdef QBOXHD_LED
114        qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_MEDIUM);
115#endif
116    cs_sleepms(500);
117    }
118  if (ret) return(0);
119
120  reader->init_history_pos=0;
121
122//  cs_ri_log("ATR: %s", cs_hexdump(1, atr, atr_size));//FIXME
123  cs_sleepms(1000);
124  return(1);
125}
126
127static void do_emm_from_file(struct s_reader * reader)
128{
129  //now here check whether we have EMM's on file to load and write to card:
130  if (reader->emmfile != NULL) {//readnano has something filled in
131
132    //handling emmfile
133    char token[256];
134    FILE *fp;
135    size_t result;
136    if ((reader->emmfile[0] == '/'))
137      snprintf (token, sizeof(token), "%s", reader->emmfile); //pathname included
138    else
139      snprintf (token, sizeof(token), "%s%s", cs_confdir, reader->emmfile); //only file specified, look in confdir for this file
140   
141    if (!(fp = fopen (token, "rb")))
142      cs_log ("ERROR: Cannot open EMM file '%s' (errno=%d %s)\n", token, errno, strerror(errno));
143    else {
144      EMM_PACKET *eptmp;
145      if(!cs_malloc(&eptmp,sizeof(EMM_PACKET), -1)){
146        fclose (fp);
147        return;
148      }
149      result = fread (eptmp, sizeof(EMM_PACKET), 1, fp);     
150      fclose (fp);
151   
152            //save old b_nano value
153            //clear lsb and lsb+1, so no blocking, and no saving for this nano 
154            uint16_t save_s_nano = reader->s_nano;
155            uint16_t save_b_nano = reader->b_nano;
156
157            int32_t rc = reader_emm(reader, eptmp);
158            if (rc == OK)
159                cs_log ("EMM from file %s was successful written.", token);
160            else
161                cs_log ("ERROR: EMM read from file %s NOT processed correctly! (rc=%d)", token, rc);
162
163            //restore old block/save settings
164            reader->s_nano = save_s_nano; 
165            reader->b_nano = save_b_nano;
166
167            free (reader->emmfile);
168            reader->emmfile = NULL; //clear emmfile, so no reading anymore
169
170            free(eptmp);
171            eptmp = NULL;
172        }
173    }
174}
175
176void reader_card_info(struct s_reader * reader)
177{
178  if ((reader->card_status == CARD_NEED_INIT) || (reader->card_status == CARD_INSERTED))
179  {
180    cur_client()->last=time((time_t)0);
181    cs_ri_brk(reader, 0);
182
183    if (reader->csystem.active && reader->csystem.card_info) {
184        reader->csystem.card_info(reader);
185    }
186  }
187}
188
189static int32_t reader_get_cardsystem(struct s_reader * reader, ATR atr)
190{
191    int32_t i;
192    for (i=0; i<CS_MAX_MOD; i++) {
193        if (cardsystem[i].card_init) {
194            if (cardsystem[i].card_init(reader, atr)) {
195                cs_log("found cardsystem %s", (cardsystem[i].desc) ? cardsystem[i].desc : "");
196                reader->csystem=cardsystem[i];
197                reader->csystem.active=1;
198#ifdef QBOXHD_LED
199                qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_MEDIUM);
200                qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN,QBOXHD_LED_BLINK_MEDIUM);
201                qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_MEDIUM);
202                qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN,QBOXHD_LED_BLINK_MEDIUM);
203#endif
204                break;
205            }
206        }
207    }
208
209    if (reader->csystem.active==0)
210#ifdef QBOXHD_LED
211    {
212        cs_ri_log(reader, "card system not supported");
213        qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_MEDIUM);
214    }
215#else
216        cs_ri_log(reader, "card system not supported");
217#endif
218
219
220
221    cs_ri_brk(reader, 1);
222
223    return(reader->csystem.active);
224}
225
226static int32_t reader_reset(struct s_reader * reader)
227{
228  reader_nullcard(reader);
229  ATR atr;
230  uint16_t ret = 0;
231#ifdef AZBOX
232  int32_t i;
233  if (reader->typ == R_INTERNAL) {
234    if (reader->mode != -1) {
235      Azbox_SetMode(reader->mode);
236      if (!reader_activate_card(reader, &atr, 0)) return(0);
237      ret = reader_get_cardsystem(reader, atr);
238    } else {
239      for (i = 0; i < AZBOX_MODES; i++) {
240        Azbox_SetMode(i);
241        if (!reader_activate_card(reader, &atr, 0)) return(0);
242        ret = reader_get_cardsystem(reader, atr);
243        if (ret)
244          break;
245      }
246    }
247  } else {
248#endif
249  uint16_t deprecated;
250    for (deprecated = reader->deprecated; deprecated < 2; deprecated++) {
251        if (!reader_activate_card(reader, &atr, deprecated)) return(0);
252        ret = reader_get_cardsystem(reader, atr);
253        if (ret)
254            break;
255        if (!deprecated)
256            cs_log("Normal mode failed, reverting to Deprecated Mode");
257    }
258#ifdef AZBOX
259  }
260#endif
261    return(ret);
262}
263
264int32_t reader_device_init(struct s_reader * reader)
265{
266    int32_t rc = -1; //FIXME
267#if defined(TUXBOX) && defined(PPC)
268    struct stat st;
269    if (!stat(DEV_MULTICAM, &st))
270        reader->typ = reader_device_type(reader);
271#endif
272    if (ICC_Async_Device_Init(reader))
273        cs_log("Cannot open device: %s", reader->device);
274    else
275        rc = OK;
276  return((rc!=OK) ? 2 : 0); //exit code 2 means keep retrying, exit code 0 means all OK
277}
278
279int32_t reader_checkhealth(struct s_reader * reader)
280{
281  if (reader_card_inserted(reader))
282  {
283    if (reader->card_status == NO_CARD || reader->card_status == UNKNOWN)
284    {
285      cs_log("%s card detected", reader->label);
286#ifdef QBOXHD_LED
287      qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_SLOW);
288#endif
289      reader->card_status = CARD_NEED_INIT;
290      if (!reader_reset(reader)) 
291      {
292        reader->card_status = CARD_FAILURE;
293        cs_log("card initializing error");
294#ifdef QBOXHD_LED
295        qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_MEDIUM);
296#endif
297      }
298      else
299      {
300        reader_card_info(reader);
301        reader->card_status = CARD_INSERTED;
302        do_emm_from_file(reader);
303      }
304    }
305  }
306  else
307  {
308    if (reader->card_status == CARD_INSERTED)
309    {
310      reader_nullcard(reader);
311      cur_client()->lastemm = 0;
312      cur_client()->lastecm = 0;
313      cs_log("card ejected");
314#ifdef QBOXHD_LED
315      qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_SLOW);
316#endif
317    }
318    reader->card_status = NO_CARD;
319  }
320  return reader->card_status == CARD_INSERTED;
321}
322
323void reader_post_process(struct s_reader * reader)
324{
325  // some systems eg. nagra2/3 needs post process after receiving cw from card
326  // To save ECM/CW time we added this function after writing ecm answer
327    if (reader->csystem.active && reader->csystem.post_process) {
328        reader->csystem.post_process(reader);
329    }
330}
331
332int32_t reader_ecm(struct s_reader * reader, ECM_REQUEST *er)
333{
334  int32_t rc=-1;
335  if( (rc=reader_checkhealth(reader)) )
336  {
337      cur_client()->last_srvid=er->srvid;
338      cur_client()->last_caid=er->caid;
339      cur_client()->last=time((time_t)0);
340
341    if (reader->csystem.active && reader->csystem.do_ecm) 
342        rc=reader->csystem.do_ecm(reader, er);
343    else
344        rc=0;
345  }
346  return(rc);
347}
348
349int32_t reader_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr) //rdr differs from calling reader!
350{
351    cs_debug_mask(D_EMM, "Entered reader_get_emm_type cardsystem %s", rdr->csystem.desc ? rdr->csystem.desc : "");
352    int32_t rc;
353
354    if (rdr->csystem.active && rdr->csystem.get_emm_type) 
355        rc=rdr->csystem.get_emm_type(ep, rdr);
356    else
357        rc=0;
358
359    return rc;
360}
361
362struct s_cardsystem *get_cardsystem_by_caid(uint16_t caid) {
363    int32_t i,j; 
364    for (i=0; i<CS_MAX_MOD; i++) { 
365        if (cardsystem[i].caids) { 
366            for (j=0;j<2;j++) { 
367                if ((cardsystem[i].caids[j]==caid >> 8)) { 
368                    return &cardsystem[i];
369                } 
370            } 
371        } 
372    } 
373    return NULL;
374} 
375
376int32_t reader_emm(struct s_reader * reader, EMM_PACKET *ep)
377{
378  int32_t rc=-1;
379
380  rc=reader_checkhealth(reader);
381  if (rc) {
382    if ((1<<(ep->emm[0] % 0x80)) & reader->b_nano)
383        return 3;
384
385    if (reader->csystem.active && reader->csystem.do_emm) 
386        rc=reader->csystem.do_emm(reader, ep);
387    else
388        rc=0;
389  }
390  return(rc);
391}
Note: See TracBrowser for help on using the repository browser.