/* en50221 encoder An implementation for libdvb an implementation for the en50221 transport layer Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com) Copyright (C) 2005 Julian Scheel (julian at jusst dot de) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "en50221_application.h" #include "dvbmisc.h" #define verbose 4 /* ------------------------------------------------------------------------- Resource Manager */ struct en50221_resource* en50221_lookup_resource(struct en50221_resource_identifier *idf) { if(!idf) return NULL; int i; struct en50221_resource *result = NULL; for(i=0;iresource_id_type && chk.resource_class == idf->resource_class && chk.resource_type == idf->resource_type) { // we ignore the version-check for now // should be implemented someday to fullfile the specs result = &resource_list[i]; break; } } return result; } // register a new resource at the Resource Manager uint8_t en50221_register_resource(struct en50221_resource_identifier *identifier, void (*callback_fct)(uint8_t *data)) { // unused elements in the resource_list have // resource_id = 0 for(i=0;i> 8) & 0x3f); data[1] = idf.resource_class & 0xff; data[2] = (idf.resource_type >> 2) & 0xff; data[3] = ((res_type & 0x03) << 6) | (res_var & 0x3f); return data; } // handle incoming TAG_PROFILE message void rm_int_handle_incoming_profile(uint8_t *data) { // the data-stream starts with the length_field; uint8_t length_field_len; if(data[0] & 0x80) length_field_len = 1; else length_field_len = 2; uint8_t *resources = data+length_field_len; uint8_t num_resources = (uint8_t) asn_1_decode(data) / 4; // each resource_identifier // has a length of 4 bytes uint8_t i; for(i = 0; i < num_resources; i++) { struct en50221_resource_identifier res; res.resource_type_id = (resources[0] >> 6) & 0x03; res.resource_class = ((resources[0] & 0x3f) << 8) | resources[1]; res.resource_type = (resources[2] << 2) | (resources[3] >> 6); res.resource_version = resources[3] & 0x3f; // register this resource // it's a null-callback, because we won't need // to pass data between modules en50221_register_resource(res, NULL); // move to the next resource resources += 4; } } // parse the APDU, and handle it depending on // the tag void en50221_rm_callback(uint8_t *data) { // strip the tag from the APDU carried in data uint32_t tag = (uint32_t ) ((((data[0] << 8) | data[1]) << 8) | data[2]); // print out the tags name struct tag_type tag_descr; get_en50221_tag(&tag_descr, tag); print(verbose, DEBUG, 1, "Received [0x%04x] %s", tag_id, tag_descr.tag_descr); switch(tag) { case TAG_PROFILE_ENQUIRY: break; case TAG_PROFILE: rm_int_handle_incoming_profile(data+3); break; } } /* ----------------------------------------------------------------------------- */ uint32_t get_en50221_tag(struct tag_types *tag_descr, uint32_t en50221_tag) { uint8_t i; uint32_t tag_id; /* get our tag */ tag_id = i = 0; while (tag_id != en50221_tag) { tag_id = (uint32_t ) ((((tag_table[i].en50221_tag[0] << 8) | tag_table[i].en50221_tag[1]) << 8) | tag_table[i].en50221_tag[2]); if (tag_id == en50221_tag) { memcpy(tag_descr->en50221_tag, tag_table[i].en50221_tag, 3); tag_descr->tag_descr = tag_table[i].tag_descr; } else { i++; } } } /* * Write to module/session layer */ void apdu_request(uint8_t slot_id, uint32_t en50221_tag) { struct tag_types en50221_tag_descr; uint32_t tag_id; get_en50221_tag(&en50221_tag_descr, en50221_tag, tag_id); print(verbose, DEBUG, 1, "Request [0x%04x] %s", tag_id, en50221_tag_descr.tag_descr); switch (tag_id) { /* length = 0 */ case TAG_PROFILE_ENQUIRY: case TAG_PROFILE_CHANGED: case TAG_APP_INFO_ENQUIRY: case TAG_ENTER_MENU: case TAG_CA_INFO_ENQUIRY: case TAG_ASK_RELEASE: /* length = 5 or 7 */ case TAG_DATE_TIME_ENQUIRY: } /* do an ASN.1 decode */ asn_1_encode(length, message); /* Req. to session layer */ en50221_sl_send_data(slot_id, message); } /* * This is a callback from the session layer * (Read from module/session layer) */ void apdu_get(int fd, uint32_t en50221_tag) { struct tag_types en50221_tag_descr; uint32_t tag_id; tag_id = get_en50221_tag(&en50221_tag_descr, en50221_tag, tag_id); print(verbose, DEBUG, 1, "Received [0x%04x] %s", tag_id, en50221_tag_descr.tag_descr); /* do an ASN.1 encode */ asn_1_decode(message); /* Read from session layer */ }