-
Notifications
You must be signed in to change notification settings - Fork 30
/
README.dvbapi_protocol
418 lines (327 loc) · 22.1 KB
/
README.dvbapi_protocol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
DVBAPI
======
DVB API stands for Linux DVB Application Programming Interface, so in short it is a set of API calls which are used on
linux to handle DVB hardware. From the OSCam point of view the most interesting part is to be able to provide all data
necessary for channel decryption. The OSCam DVBAPI module was written to handle this work.
Architecture
============
A DVBAPI module needs the following information to decrypt a channel:
- PMT table (information from TV receiver software about the requested channel for livetv/recording and the ECM PIDs)
- CAT table (needed to get information about EMM type and PIDs)
- Filtered ECM/EMM data
If OSCam is able to decrypt a service, information about the decrypted PIDs (audio, video, etc) and CW (keys)
is sent back to the TV receiver software from the CAM device.
History
=======
The first and "standard" use case is probably Enigma. OSCam creates a /tmp/camd.socket. Enigma sends the PMT data to
this socket and as a result OSCam opens the necessary DVB demux devices (e.g. /dev/dvb/adapter0/demux0) and filters
for ECM, CAT and EMM data. These data are then parsed by the OSCam dvbapi module and as a result the CA_SET_PID and
CA_SET_DESCR ioctl calls are made, leading to proper decryption. All this was working on the same hardware and the
same DVB devices were used. This kind of usage was mainly for linux STB.
Next step was generic PC support, by extending the dvbapi module to send PIDs and keys back to TV software (initially
via a special UDP socket, later via the same /tmp/camd.socket). The TV software was able to use this information in
software decryption (DeCSA).
At some point, the OpenPLi team created a new CaPMT interface, which was then implemented in OSCam (as pmt_mode=6).
It is described here: http://wiki.openpli.org/caPMT
The main feature was reverting the roles: OSCam now acts as a client and connects to /tmp/.listen.camd.socket created
by Enigma. This way multiple Software CAMs could be running and connecting to Enigma's .listen.camd.socket. Another
important improvement in this mode (also implemented in OSCam) was the ability to handle extra CA_PMT list managements.
This allows to use one socket connection to handle more than one channel at a time (previously clients had to manage
a single connection to /tmp/camd.socket per subscribed channel).
As the .listen.camd.socket mode makes less sense on generic PC platform (the OSCam is still server, while the client
could be any PC software used), the second feature which allows handling multiple channels on single socket connection
was extended to cover other modes (not only pmt_mode=6) in OSCam.
Network mode
============
The last feature that was added was a network mode. The change was made to be able to connect to an OSCam instance
which is not running on the same machine where the TV receiver software (and a DVB hardware) runs.
Why not use dedicated protocols like newcamd/camd in such cases?
- To have ECM/EMM handling in OSCam, where it belongs. It is better maintained and fixes come in quicker.
- OSCam knows what readers it has, so it could do load balance/filtering/priorities etc.
As a result, instead of /tmp/camd.socket (which could be used only on the same machine) a listening_socket parameter
was added. So the unix domain socket switched to a fully-featured TCP socket which can be connected from any network
client.
As a result besides CA_SET_PID and CA_SET_DESCR new calls were passed to socket: DMX_SET_FILTER and DMX_STOP. The TV
receiver software has to filter the demux itself (according to the new calls above) and send results like ECM/EMM/CAT
data back to OSCam using the same connection. Because OSCam was only aware of PMT data on the socket, a new
DVBAPI_FILTER_DATA command (0xffff0000) was added to handle client data from filters.
This way, communication between the TV receiver software and OSCam could be finally done using only one single TCP
connection. Moreover, the demux is only accessed by a single TV receiver software process, which from the architecture's
point of view is definitely a better solution.
New protocol description (socket commands)
===========================================
As there are more and more dvbapi clients, some problems start to appear. First of all there was some kind of mess
because OSCam's network mode doesn't take into account the endianness in first form of the network protocol. Second,
it was not consistant (e.g. PID was always send as little endian in DMX_STOP, while the rest depend on OSCam's host
architecture). Finally the standard API ioctl codes for CA_SET_PID, CA_SET_DESCR, DMX_SET_FILTER and DMX_STOP behave
differently. These codes are composed by a macro which takes into account the length of the associated structures and
on some hardware the first bits of the MSB was different. So the clients had to do some strange workarounds with
the MSB byte: fix 0x80 -> 0x40 and 0x20 -> 0x00 when needed
Finally, the first byte sent to client was an adapter index, which was not always needed in all commands. Now the
first 4-byte integer is unique operation code, so a client will know what is the request type and could read the rest
of data according to the following description (and field sizes).
To address all above problems and additionally make smooth transitions when updating the protocol in the future there
was added some kind of "handshake" for clients. All new implementations should use it. Currently the old and new
implementations should work fine, but in the future a network client which will not introduce itself (thus not providing
it's supported protocol version) may be dropped/ignored by OSCam.
All multibyte integers (if not specified otherwise) should be send using network byte order, so your client should use
ntoh() functions when receiving. OSCam is doing hton() before sending and vice versa.
Just right after a client connects to an OSCam network socket, it should send a greeting in format:
-= DVBAPI_CLIENT_INFO =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_CLIENT_INFO
uint16_t protocol version supported by client
uint8_t size of followed string (255 bytes max)
string name and version of the client (string length should be max 255 bytes)
The server will respond with a similar reply:
-= DVBAPI_SERVER_INFO =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_SERVER_INFO
uint16_t protocol version supported by OSCam
uint8_t size of followed string (255 bytes max)
string OSCam version and build (string length should be max 255 bytes)
Next, when a client wants to start a channel, it should send the PMT data (program map table). The PMT data structure
starts with constant AOT_CA_PMT (0x9F8032). The data format of the CA_PMT is described in chapter 8.4.3.4 (page 30) of
the EN 50221 PDF (european standard).
-------------------------------------------------------------------------------
Please note that OSCam is expecting a number of private descriptors injected
into the CA PMT data. They shall be located inside the program info loop. All
supported descriptors follow the structure defined in 2.6 of Rec. ITU H.222.0
and they are the following:
---------------------------------------------------------------------
| descriptor_tag | Identification | Usage |
---------------------------------------------------------------------
| 0x81 | enigma_namespace_descriptor | optional |
| 0x82 | demux_ca_mask_device_descriptor | deprecated |
| 0x83 | adapter_device_descriptor | mandatory |
| 0x84 | pmt_pid_descriptor | mandatory |
| 0x85 | service_type_mask_descriptor | optional |
| 0x86 | demux_device_descriptor | mandatory |
| 0x87 | ca_device_descriptor | mandatory |
---------------------------------------------------------------------
Descriptors marked as "mandatory" shall be present in the CA PMT message, in
order OSCam to get all necessary information for the specified program. Below
is a detailed description for each of the supported descriptors with its
structure and usage.
-------------------------------------------------------------------------------
1. Enigma namespace descriptor
Provides additional information for the program specified, such as enigma
namespace (orbital position, frequency and polarization), transport stream id
and original network id. Although its presense in the CA PMT is optional, it
is advised to be included as OSCam utilizes these information in many aspects.
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| enigma_namespace_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| enigma_namespace | 32 | uimsbf |
| transport_stream_id | 16 | uimsbf |
| original_network_id | 16 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x81.
descriptor_length - The length of the descriptor is equal to 0x08.
ens - This is the enigma namespace as defined in OpenPLi, openATV and other
open enigma2 images. An example implementation can be found at:
https://github.com/OpenPLi/enigma2/blob/develop/lib/dvb/frontend.cpp#L476
transport_stream_id – The transport stream id as defined in various DVB SI
tables.
original_network_id - The original network id as defined in various DVB SI
tables.
-------------------------------------------------------------------------------
2. Demux and ca mask device descriptor
It was used to provide information about the demux device as well as the ca
device(s) carrying the specified program. It was created for the DM7025 set top
box and it is now considered deprecated. Many hosts use this descriptor in a
different way (carrying different information) than it was originaly designed
leading to confusion. OSCam will continue to support this descriptor as some
legacy hosts still use it. For newer hosts, the adapter_device_descriptor (tag
0x83), the demux_device_descriptor (tag 0x86) and the ca_device_descriptor (tag
0x87) shall be used for sending the necessary data to OSCam.
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| demux_ca_mask_device_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| ca_mask | 8 | uimsbf |
| demux_device | 8 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x82.
descriptor_length - The length of the descriptor is equal to 0x02.
ca_mask - It is a bit mask of the ca device(s) carrying the specified program.
Bit 0 corresonds to ca0, bit 1 corresponds to ca1 and so on.
demux_device - The demux device that carries the specified program. It is
limited to values between 0x00 and 0x08 in older enigma2 images.
-------------------------------------------------------------------------------
3. Adapter device descriptor
Provides information about the adapter device carrying the specified program.
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| adapter_device_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| adapter_device | 8 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x83.
descriptor_length - The length of the descriptor is equal to 0x01.
adapter_device - The adapter device that carries the specified program. It can
take values from 0x00 to 0xFF, thus a maximum number of different 256 adapters
are supported.
-------------------------------------------------------------------------------
4. PMT pid descriptor
Provides information about the PMT pid of the specified program.
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| pmt_pid_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| pmt_pid | 16 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x84.
descriptor_length - The length of the descriptor is equal to 0x02.
pmt_pid - The pid that carries the PMT table of the specified program.
-------------------------------------------------------------------------------
5. Service type mask descriptor
It provides information about the type (live tv, recording, streaming service,
or any combination) of the program specified. It's currently not unitilized in
OSCam and its usage in considered optional.
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| service_type_mask_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| service_type_mask | 32 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x85.
descriptor_length - The length of the descriptor is equal to 0x04.
service_type_mask - This is a bit mask of the different service types enabled
for the specified program. Service type values are defined in enigma2 and can
be found at https://github.com/OpenPLi/enigma2/blob/develop/lib/dvb/pmt.h#L135
-------------------------------------------------------------------------------
6. Demux device descriptor
It is used to provide information about the demux device carrying the specified
program. It is a replacement to the deprecated demux_ca_mask_device_descriptor
(tag 0x82), as it supports up to 256 different demux devices.
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| demux_device_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| demux_device | 8 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x86.
descriptor_length - The length of the descriptor is equal to 0x01.
demux_device - The demux device that carries the specified program. Its value
can be between 0x00 and 0xFF.
-------------------------------------------------------------------------------
7. Ca device descriptor
This descriptor provides OSCam with information about the ca device carrying
the specified program. It is created as a replacement to the deprecated
demux_ca_mask_device_descriptor (tag 0x82). It has the following syntax:
---------------------------------------------------------------------
| Syntax | No. of bits | Mnemonic |
---------------------------------------------------------------------
| ca_device_descriptor(){ | | |
| descriptor_tag | 8 | uimsbf |
| descriptor_length | 8 | uimsbf |
| ca_device | 8 | uimsbf |
| } | | |
---------------------------------------------------------------------
decriptor_tag - The tag of the descriptor is equal to 0x87.
descriptor_length - The length of the descriptor is equal to 0x01.
ca_device - The ca device that carries the specified program. Its value can be
between 0x00 and 0xFF (256 different ca devices supported).
-------------------------------------------------------------------------------
After OSCam parses the PMT data, it starts filtering ECM PIDs. It sends the following request to the client:
-= DVBAPI_DMX_SET_FILTER =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_DMX_SET_FILTER
uint8_t adapter index
uint8_t demux index
uint8_t filter number
*** The following data are the fields from the dmx_sct_filter_params structure (added separately to avoid padding problems)
uint16_t pid
uint8_t[16] filter data (filter.filter)
uint8_t[16] filter mask (filter.mask)
uint8_t[16] filter mode (filter.mode)
uint32_t timeout
uint32_t flags
The client should then filter the data and pass it back to OSCam using the following frame:
-= DVBAPI_FILTER_DATA =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_FILTER_DATA
uint8_t demux index
uint8_t filter number
uint8_t[] filtered data from demux
When OSCam is able to decrypt a channel, it initially sends a list of PIDs associated with the descrambler index using
this packet:
-= DVBAPI_CA_SET_PID =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_CA_SET_PID
uint8_t adapter index
ca_pid_t 8-byte ca_pid_t structure (the pid and index fields are in network byte order)
And also sends the CW for decryption:
-= DVBAPI_CA_SET_DESCR =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_CA_SET_DESCR
uint8_t adapter index
ca_descr_t 16-byte ca_descr_t structure (the index and parity fields are in network byte order)
When OSCam wants to inform the client about stopping a filter, it sends the following packet:
-= DVBAPI_DMX_STOP =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_DMX_STOP
uint8_t adapter index
uint8_t demux index
uint8_t filter number
uint16_t PID to stop filtering
When the client closes connection, all associated channels are stopped in OSCam.
Alternatively when there is a need to stop channel decoding, while having the connection still open you can send a
special '3f' packed to OSCam. To stop decoding the specified demux, the following CA_PMT data should be sent to OSCam:
9F 80 3f 04 83 02 00 <demux index>
If <demux index> is 0xff, then it is parsed as a wildcard and all demuxers associated with the connection are stopped.
In protocol version 2 the new packet with ECM info data was introduced:
-= DVBAPI_ECM_INFO =-
-----------------------------------------------------------------------
type/size description
-----------------------------------------------------------------------
uint32_t operation code -> DVBAPI_ECM_INFO
uint8_t adapter index
uint16_t Service ID
uint16_t CAID
uint16_t PID
uint32_t Provider ID
uint32_t ECM time (ms)
uint8_t size of followed string (255 bytes max)
string cardsystem name (string length should be max 255 bytes)
uint8_t size of followed string (255 bytes max)
string reader name (string length should be max 255 bytes)
uint8_t size of followed string (255 bytes max)
string from - source name (string length should be max 255 bytes)
uint8_t size of followed string (255 bytes max)
string protocol name (string length should be max 255 bytes)
uint8_t hops (cccam & gbox; set to 0 otherwise)