source: trunk/module-dvbapi-azbox.c@ 8367

Last change on this file since 8367 was 8367, checked in by gf, 9 years ago

Remove four unused variables from struct s_client.

Save at least 148 bytes per client.

  • Property svn:eol-style set to LF
File size: 10.1 KB
Line 
1#include "globals.h"
2
3#if defined(HAVE_DVBAPI) && defined(WITH_AZBOX)
4
5#include "extapi/openxcas/openxcas_api.h"
6#include "extapi/openxcas/openxcas_message.h"
7
8#include "module-dvbapi.h"
9#include "module-dvbapi-azbox.h"
10#include "oscam-client.h"
11#include "oscam-ecm.h"
12#include "oscam-reader.h"
13#include "oscam-string.h"
14#include "oscam-time.h"
15
16#define LOG_PREFIX "openxcas: "
17#define LOG_PREFIX_MSG "openxcasmsg: "
18
19// These variables are declared in module-dvbapi.c
20extern void * dvbapi_client;
21extern DEMUXTYPE demux[MAX_DEMUX];
22
23// These are used in module-dvbapi.c
24int32_t openxcas_provid;
25uint16_t openxcas_sid, openxcas_caid, openxcas_ecm_pid;
26
27static unsigned char openxcas_cw[16];
28static int32_t openxcas_seq, openxcas_filter_idx, openxcas_stream_id, openxcas_cipher_idx, openxcas_busy;
29static uint16_t openxcas_video_pid, openxcas_audio_pid, openxcas_data_pid;
30
31void azbox_openxcas_ecm_callback(int32_t stream_id, uint32_t UNUSED(seq), int32_t cipher_index, uint32_t UNUSED(caid), unsigned char *ecm_data, int32_t l, uint16_t pid) {
32 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm callback received");
33
34 openxcas_stream_id = stream_id;
35 //openxcas_seq = seq;
36 //openxcas_caid = caid;
37 openxcas_ecm_pid = pid;
38 openxcas_busy = 1;
39
40 ECM_REQUEST *er;
41 if (!(er=get_ecmtask()))
42 return;
43
44 er->srvid = openxcas_sid;
45 er->caid = openxcas_caid;
46 er->pid = openxcas_ecm_pid;
47 er->prid = openxcas_provid;
48
49 er->ecmlen = l;
50 memcpy(er->ecm, ecm_data, er->ecmlen);
51
52 request_cw(dvbapi_client, er);
53
54 //openxcas_stop_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
55 //openxcas_remove_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
56
57 openxcas_cipher_idx = cipher_index;
58
59 struct timeb tp;
60 cs_ftime(&tp);
61 tp.time+=500;
62}
63
64
65void azbox_openxcas_ex_callback(int32_t stream_id, uint32_t seq, int32_t idx, uint32_t pid, unsigned char *ecm_data, int32_t l) {
66 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ex callback received");
67
68 openxcas_stream_id = stream_id;
69 openxcas_ecm_pid = pid;
70 openxcas_cipher_idx = idx; // is this really cipher_idx?
71
72 ECM_REQUEST *er;
73 if (!(er=get_ecmtask()))
74 return;
75
76 er->srvid = openxcas_sid;
77 er->caid = openxcas_caid;
78 er->pid = openxcas_ecm_pid;
79 er->prid = openxcas_provid;
80
81 er->ecmlen = l;
82 memcpy(er->ecm, ecm_data, er->ecmlen);
83
84 request_cw(dvbapi_client, er);
85
86 if (openxcas_stop_filter_ex(stream_id, seq, openxcas_filter_idx) < 0)
87 cs_log(LOG_PREFIX "unable to stop ex filter");
88 else
89 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ex filter stopped");
90
91
92
93 unsigned char mask[12];
94 unsigned char comp[12];
95 memset(&mask, 0x00, sizeof(mask));
96 memset(&comp, 0x00, sizeof(comp));
97
98 mask[0] = 0xff;
99 comp[0] = ecm_data[0] ^ 1;
100
101 if ((openxcas_filter_idx = openxcas_start_filter_ex(stream_id, seq, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ex_callback)) < 0)
102 cs_log(LOG_PREFIX "unable to start ex filter");
103 else
104 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ex filter started, pid = %x", openxcas_ecm_pid);
105}
106
107void * azbox_main_thread(void *cli) {
108 struct s_client * client = (struct s_client *) cli;
109 client->thread=pthread_self();
110 pthread_setspecific(getclient, cli);
111 dvbapi_client=cli;
112
113 struct s_auth *account;
114 int32_t ok = 0;
115 for (account = cfg.account; account; account=account->next) {
116 if ((ok = streq(cfg.dvbapi_usr, account->usr)))
117 break;
118 }
119 cs_auth_client(client, ok ? account : (struct s_auth *)(-1), "dvbapi");
120
121 dvbapi_read_priority();
122
123 openxcas_msg_t msg;
124 int32_t ret;
125 while ((ret = openxcas_get_message(&msg, 0)) >= 0) {
126 cs_sleepms(10);
127
128 if (ret) {
129 openxcas_stream_id = msg.stream_id;
130 openxcas_seq = msg.sequence;
131
132 switch(msg.cmd) {
133 case OPENXCAS_SELECT_CHANNEL:
134 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_SELECT_CHANNEL");
135
136 // parse channel info
137 struct stOpenXCASChannel chan;
138 memcpy(&chan, msg.buf, msg.buf_len);
139
140 cs_log(LOG_PREFIX "channel change: sid = %x, vpid = %x. apid = %x", chan.service_id, chan.v_pid, chan.a_pid);
141
142 openxcas_video_pid = chan.v_pid;
143 openxcas_audio_pid = chan.a_pid;
144 openxcas_data_pid = chan.d_pid;
145 break;
146 case OPENXCAS_START_PMT_ECM:
147 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_START_PMT_ECM");
148
149 // parse pmt
150 uchar *dest;
151 if (!cs_malloc(&dest, msg.buf_len + 7 - 12 - 4))
152 break;
153
154 memcpy(dest, "\x00\xFF\xFF\x00\x00\x13\x00", 7);
155
156 dest[1] = msg.buf[3];
157 dest[2] = msg.buf[4];
158 dest[5] = msg.buf[11]+1;
159
160 memcpy(dest + 7, msg.buf + 12, msg.buf_len - 12 - 4);
161
162 dvbapi_parse_capmt(dest, 7 + msg.buf_len - 12 - 4, -1, NULL);
163 free(dest);
164
165 unsigned char mask[12];
166 unsigned char comp[12];
167 memset(&mask, 0x00, sizeof(mask));
168 memset(&comp, 0x00, sizeof(comp));
169
170 mask[0] = 0xfe;
171 comp[0] = 0x80;
172
173 if ((ret = openxcas_add_filter(msg.stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback)) < 0)
174 cs_log(LOG_PREFIX "unable to add ecm filter");
175 else
176 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0);
177
178 if (openxcas_start_filter(msg.stream_id, msg.sequence, OPENXCAS_FILTER_ECM) < 0)
179 cs_log(LOG_PREFIX "unable to start ecm filter");
180 else
181 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter started");
182
183 if (!openxcas_create_cipher_ex(msg.stream_id, openxcas_seq, 0, openxcas_ecm_pid, openxcas_video_pid, 0xffff, openxcas_audio_pid, 0xffff, 0xffff, 0xffff))
184 cs_log(LOG_PREFIX "failed to create cipher ex");
185 else
186 cs_debug_mask(D_DVBAPI, LOG_PREFIX "cipher created");
187 break;
188 case OPENXCAS_STOP_PMT_ECM:
189 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_STOP_PMT_ECM");
190 openxcas_stop_filter(msg.stream_id, OPENXCAS_FILTER_ECM);
191 openxcas_remove_filter(msg.stream_id, OPENXCAS_FILTER_ECM);
192 openxcas_stop_filter_ex(msg.stream_id, msg.sequence, openxcas_filter_idx);
193 openxcas_destory_cipher_ex(msg.stream_id, msg.sequence);
194 memset(&demux, 0, sizeof(demux));
195 break;
196 case OPENXCAS_ECM_CALLBACK:
197 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_ECM_CALLBACK");
198 struct stOpenXCAS_Data data;
199 memcpy(&data, msg.buf, msg.buf_len);
200 if (!openxcas_busy)
201 openxcas_filter_callback(msg.stream_id, msg.sequence, OPENXCAS_FILTER_ECM, &data);
202 break;
203 case OPENXCAS_PID_FILTER_CALLBACK:
204 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_PID_FILTER_CALLBACK");
205 openxcas_filter_callback_ex(msg.stream_id, msg.sequence, (struct stOpenXCAS_Data *)msg.buf);
206 break;
207 case OPENXCAS_QUIT:
208 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_QUIT");
209 openxcas_close();
210 cs_log(LOG_PREFIX "exited");
211 return NULL;
212 break;
213 case OPENXCAS_UKNOWN_MSG:
214 default:
215 cs_debug_mask(D_DVBAPI, LOG_PREFIX_MSG "OPENXCAS_UKNOWN_MSG (%d)", msg.cmd);
216 //cs_ddump_mask(D_DVBAPI, &msg, sizeof(msg), "msg dump:");
217 break;
218 }
219 }
220 }
221 cs_log(LOG_PREFIX "invalid message");
222 return NULL;
223}
224
225void azbox_send_dcw(struct s_client *client, ECM_REQUEST *er) {
226 cs_debug_mask(D_DVBAPI, LOG_PREFIX "send_dcw");
227
228 FILE *ecmtxt;
229 if ((ecmtxt = fopen(ECMINFO_FILE, "w"))) {
230 char tmp[25];
231 if(er->rc <= E_CACHEEX) {
232 fprintf(ecmtxt, "caid: 0x%04X\npid: 0x%04X\nprov: 0x%06X\n", er->caid, er->pid, (uint) er->prid);
233 fprintf(ecmtxt, "reader: %s\n", er->selected_reader->label);
234 if (is_cascading_reader(er->selected_reader))
235 fprintf(ecmtxt, "from: %s\n", er->selected_reader->device);
236 else
237 fprintf(ecmtxt, "from: local\n");
238 fprintf(ecmtxt, "protocol: %s\n", reader_get_type_desc(er->selected_reader, 1));
239 fprintf(ecmtxt, "hops: %d\n", er->selected_reader->currenthops);
240 fprintf(ecmtxt, "ecm time: %.3f\n", (float) client->cwlastresptime/1000);
241 fprintf(ecmtxt, "cw0: %s\n", cs_hexdump(1,demux[0].lastcw[0],8, tmp, sizeof(tmp)));
242 fprintf(ecmtxt, "cw1: %s\n", cs_hexdump(1,demux[0].lastcw[1],8, tmp, sizeof(tmp)));
243 fclose(ecmtxt);
244 ecmtxt = NULL;
245 } else {
246 fprintf(ecmtxt, "ECM information not found\n");
247 fclose(ecmtxt);
248 }
249 }
250
251 openxcas_busy = 0;
252
253 int32_t i;
254 for (i=0; i < MAX_DEMUX; i++) {
255 if (er->rc >= E_NOTFOUND) {
256 cs_debug_mask(D_DVBAPI, "cw not found");
257
258 if (demux[i].pidindex==-1)
259 dvbapi_try_next_caid(i);
260
261 openxcas_stop_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
262 openxcas_remove_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM);
263
264 unsigned char mask[12];
265 unsigned char comp[12];
266 memset(&mask, 0x00, sizeof(mask));
267 memset(&comp, 0x00, sizeof(comp));
268
269 mask[0] = 0xfe;
270 comp[0] = 0x80;
271
272 if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, 0, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0) {
273 cs_log(LOG_PREFIX "unable to add ecm filter (0)");
274 if (openxcas_add_filter(openxcas_stream_id, OPENXCAS_FILTER_ECM, openxcas_caid, 0xffff, openxcas_ecm_pid, mask, comp, (void *)azbox_openxcas_ecm_callback) < 0)
275 cs_log(LOG_PREFIX "unable to add ecm filter (%04x)", openxcas_caid);
276 else
277 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, openxcas_caid);
278 } else
279 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter added, pid = %x, caid = %x", openxcas_ecm_pid, 0);
280
281 if (openxcas_start_filter(openxcas_stream_id, openxcas_seq, OPENXCAS_FILTER_ECM) < 0)
282 cs_log(LOG_PREFIX "unable to start ecm filter");
283 else
284 cs_debug_mask(D_DVBAPI, LOG_PREFIX "ecm filter started");
285
286 return;
287 }
288 }
289
290 unsigned char nullcw[8];
291 memset(nullcw, 0, 8);
292
293 int32_t n;
294 for (n=0;n<2;n++) {
295 if (memcmp(er->cw + (n * 8), demux[0].lastcw[n], 8) && memcmp(er->cw + (n * 8), nullcw, 8)) {
296 memcpy(demux[0].lastcw[n], er->cw + (n * 8), 8);
297 memcpy(openxcas_cw + (n * 8), er->cw + (n * 8), 8);
298 }
299 }
300
301 if (openxcas_set_key(openxcas_stream_id, openxcas_seq, 0, openxcas_cipher_idx, openxcas_cw, openxcas_cw + 8) != 1)
302 cs_log(LOG_PREFIX "set cw failed");
303 else
304 cs_ddump_mask(D_DVBAPI, openxcas_cw, 16, LOG_PREFIX "write cws to descrambler");
305}
306
307#ifdef WITH_CARDREADER
308#define __openxcas_open openxcas_open_with_smartcard
309#else
310#define __openxcas_open openxcas_open
311#endif
312
313void azbox_init(void) {
314 openxcas_debug_message_onoff(1); // debug
315 if (__openxcas_open("oscamCAS") < 0)
316 cs_log(LOG_PREFIX "could not init");
317}
318
319void azbox_close(void) {
320 if (openxcas_close() < 0)
321 cs_log(LOG_PREFIX "could not close");
322}
323
324#endif
Note: See TracBrowser for help on using the repository browser.