static void start_bss_network(struct adapter *padapter, u8 *pbuf) { u8 *p; u8 val8, cur_channel, cur_bwmode, cur_ch_offset; u16 bcn_interval; u32 acparm; uint ie_len; struct registry_priv *pregpriv = &padapter->registrypriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct security_priv *psecuritypriv = &padapter->securitypriv; struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; struct HT_info_element *pht_info = NULL; bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod; cur_channel = pnetwork->Configuration.DSConfig; cur_bwmode = HT_CHANNEL_WIDTH_20; cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; /* check if there is wps ie, * if there is wpsie in beacon, the hostapd will update * beacon twice when stating hostapd, and at first time the * security ie (RSN/WPA IE) will not include in beacon. */ if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_, pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; /* todo: update wmm, ht cap */ if (pmlmepriv->qospriv.qos_option) pmlmeinfo->WMM_enable = true; if (pmlmepriv->htpriv.ht_option) { pmlmeinfo->WMM_enable = true; pmlmeinfo->HT_enable = true; update_hw_ht_param(padapter); } /* setting only at first time */ if (pmlmepriv->cur_network.join_res != true) { /* WEP Key will be set before this function, do not * clear CAM. */ if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)) flush_all_cam_entry(padapter); /* clear CAM */ } /* set MSR to AP_Mode */ Set_MSR(padapter, _HW_STATE_AP_); /* Set BSSID REG */ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress); /* Set EDCA param reg */ acparm = 0x002F3217; /* VO */ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm)); acparm = 0x005E4317; /* VI */ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm)); acparm = 0x005ea42b; rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm)); acparm = 0x0000A444; /* BK */ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm)); /* Set Security */ val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); /* Beacon Control related register */ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval)); UpdateBrateTbl(padapter, pnetwork->SupportedRates); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); if (!pmlmepriv->cur_network.join_res) { /* setting only at first time */ /* turn on all dynamic functions */ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); } /* set channel, bwmode */ p = rtw_get_ie((pnetwork->ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - sizeof(struct ndis_802_11_fixed_ie))); if (p && ie_len) { pht_info = (struct HT_info_element *)(p + 2); if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) { /* switch to the 40M Hz mode */ cur_bwmode = HT_CHANNEL_WIDTH_40; switch (pht_info->infos[0] & 0x3) { case 1: cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; break; case 3: cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; break; default: cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; break; } } } /* TODO: need to judge the phy parameters on concurrent * mode for single phy */ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, cur_ch_offset); /* */ pmlmeext->cur_channel = cur_channel; pmlmeext->cur_bwmode = cur_bwmode; pmlmeext->cur_ch_offset = cur_ch_offset; pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; /* update cur_wireless_mode */ update_wireless_mode(padapter); /* update capability after cur_wireless_mode updated */ update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork)); /* let pnetwork_mlmeext == pnetwork_mlme. */ memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); if (pmlmeext->bstart_bss) { update_beacon(padapter, _TIM_IE_, NULL, false); /* issue beacon frame */ if (send_beacon(padapter) == _FAIL) DBG_88E("send_beacon, fail!\n"); } /* update bc/mc sta_info */ update_bmc_sta(padapter); }
struct ccx_demuxer *init_demuxer(void *parent, struct demuxer_cfg *cfg) { int i; struct ccx_demuxer *ctx = malloc(sizeof(struct ccx_demuxer)); if(!ctx) return NULL; ctx->infd = -1;//Set to -1 to indicate no file is open. ctx->m2ts = cfg->m2ts; ctx->auto_stream = cfg->auto_stream; ctx->stream_mode = CCX_SM_ELEMENTARY_OR_NOT_FOUND; ctx->ts_autoprogram = cfg->ts_autoprogram; ctx->ts_allprogram = cfg->ts_allprogram; ctx->ts_datastreamtype = cfg->ts_datastreamtype; ctx->nb_program = 0; ctx->multi_stream_per_prog = 0; if(cfg->ts_forced_program != -1) { ctx->pinfo[ctx->nb_program].pid = CCX_UNKNOWN; ctx->pinfo[ctx->nb_program].program_number = cfg->ts_forced_program; ctx->flag_ts_forced_pn = CCX_TRUE; ctx->nb_program++; } else { ctx->flag_ts_forced_pn = CCX_FALSE; } INIT_LIST_HEAD(&ctx->cinfo_tree.all_stream); INIT_LIST_HEAD(&ctx->cinfo_tree.sib_stream); INIT_LIST_HEAD(&ctx->cinfo_tree.pg_stream); ctx->codec = cfg->codec; ctx->flag_ts_forced_cappid = CCX_FALSE; for(i = 0; i < cfg->nb_ts_cappid; i++) { if(ctx->codec == CCX_CODEC_ANY) update_capinfo(ctx, cfg->ts_cappids[i], cfg->ts_datastreamtype, CCX_CODEC_NONE, 0, NULL); else update_capinfo(ctx, cfg->ts_cappids[i], cfg->ts_datastreamtype, ctx->codec, 0, NULL); } ctx->flag_ts_forced_cappid = cfg->nb_ts_cappid ? CCX_TRUE : CCX_FALSE; ctx->nocodec = cfg->nocodec; ctx->reset = ccx_demuxer_reset; ctx->close = ccx_demuxer_close; ctx->open = ccx_demuxer_open; ctx->is_open = ccx_demuxer_isopen; ctx->get_filesize = ccx_demuxer_getfilesize; ctx->get_stream_mode = ccx_demuxer_get_stream_mode; ctx->print_cfg = ccx_demuxer_print_cfg; ctx->write_es = ccx_demuxer_write_es; ctx->hauppauge_warning_shown = 0; ctx->parent = parent; ctx->last_pat_payload = NULL; ctx->last_pat_length = 0; ctx->fh_out_elementarystream = NULL; ctx->warning_program_not_found_shown = CCX_FALSE; ctx->strangeheader = 0; memset(&ctx->freport, 0, sizeof(ctx->freport)); if (cfg->out_elementarystream_filename != NULL) { if ((ctx->fh_out_elementarystream = fopen (cfg->out_elementarystream_filename,"wb"))==NULL) { print_error(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s\n", cfg->out_elementarystream_filename); return NULL; } } for(i = 0; i < MAX_PSI_PID; i++) ctx->PID_buffers[i]=NULL; init_ts(ctx); ctx->filebuffer = NULL; return ctx; }
int parse_PMT (struct ccx_demuxer *ctx, unsigned char *buf, int len, struct program_info *pinfo) { int must_flush = 0; int ret = 0; unsigned char desc_len = 0; unsigned char *sbuf = buf; unsigned int olen = len; uint32_t crc; uint8_t table_id; uint16_t section_length; uint16_t program_number; uint8_t version_number; uint8_t current_next_indicator; uint8_t section_number; uint8_t last_section_number; uint16_t pi_length; crc = (*(int32_t*)(sbuf+olen-4)); table_id = buf[0]; /* TO-DO: We're currently parsing the PMT making assumptions that there's only one section with table_id=2, but that doesn't have to be the case. There's a sample (friends_tbs.ts) that shows a previous section with table_id = 0xc0. I can't find any place that says that 0xc0 (Program Information Table) must come before table_id = 2, so we should process sections in any order. Check https://github.com/CCExtractor/ccextractor/issues/385 for more info */ if (table_id == 0xC0) { /* * Acc to System Information for Satellite Distribution * of Digital Television for Cable and MMDS (ANSI/SCTE 57 2003 ) * PROGRAM INFORMATION Table found in PMT */ dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM INFORMATION Table need implementation"); // For now, just parse its length and remove it from the buffer unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes dbg_print(CCX_DMT_PARSE, "Program information table length: %u", c0length); memmove(buf, buf + c0length + 3, len - c0length -3); // First 3 bytes are for the table_id and the length, don't count table_id = buf[0]; // return 0; } else if (table_id == 0xC1) { //SCTE 57 2003 dbg_print(CCX_DMT_PARSE, "PMT: PROGRAM NAME Table need implementation"); unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF; // 12 bytes dbg_print(CCX_DMT_PARSE, "Program name message length: %u", c0length); memmove(buf, buf + c0length + 3, len - c0length - 3); // First 3 bytes are for the table_id and the length, don't count table_id = buf[0]; //return 0; } else if(table_id != 0x2) { mprint("Please Report: Unknown table id in PMT expected 0x02 found 0x%X\n", table_id); return 0; } section_length = (((buf[1] & 0x0F) << 8)| buf[2]); if(section_length > (len - 3)) { return 0; //We don't have the full section yet. We will parse again when we have it. } program_number = ((buf[3] << 8) | buf[4]); version_number = (buf[5] & 0x3E) >> 1; current_next_indicator = buf[5] & 0x01; // This table is not active, no need to evaluate if (!current_next_indicator) return 0; memcpy (pinfo->saved_section, buf, len); if (pinfo->analysed_PMT_once == CCX_TRUE && pinfo->version == version_number) { if (pinfo->version == version_number) { /* Same Version number and there was valid or similar CRC last time */ if ( pinfo->valid_crc == CCX_TRUE || pinfo->crc == crc ) return 0; } else if ( (pinfo->version+1)%32 != version_number) mprint("TS PMT:Glitch in version number incremnt"); } pinfo->version = version_number; section_number = buf[6]; last_section_number = buf[7]; if ( last_section_number > 0 ) { mprint("Long PMTs are not supported - skipped.\n"); return 0; } pinfo->pcr_pid = (((buf[8] & 0x1F) << 8) | buf[9]); pi_length = (((buf[10] & 0x0F) << 8) | buf[11]); if( 12 + pi_length > len ) { // If we would support long PMTs, this would be wrong. mprint("program_info_length cannot be longer than the payload_length - skipped\n"); return 0; } buf += 12 + pi_length; len -= (12 + pi_length); unsigned stream_data = section_length - 9 - pi_length - 4; // prev. bytes and CRC dbg_print(CCX_DMT_PARSE, "Read PMT packet (id: %u) program number: %u\n", table_id, program_number); dbg_print(CCX_DMT_PARSE, " section length: %u number: %u last: %u\n", section_length, section_number, last_section_number); dbg_print(CCX_DMT_PARSE, " version_number: %u current_next_indicator: %u\n", version_number, current_next_indicator); dbg_print(CCX_DMT_PARSE, " PCR_PID: %u data length: %u payload_length: %u\n", pinfo->pcr_pid, stream_data, len); if (!pmt_warning_shown && stream_data+4 > len ) { dbg_print (CCX_DMT_GENERIC_NOTICES, "\rWarning: Probably parsing incomplete PMT, expected data longer than available payload.\n"); pmt_warning_shown=1; } // Make a note of the program number for all PIDs, so we can report it later for( unsigned i=0; i < stream_data && (i+4)<len; i+=5) { enum ccx_stream_type stream_type = buf[i]; unsigned elementary_PID = (((buf[i+1] & 0x1F) << 8) | buf[i+2]); unsigned ES_info_length = (((buf[i+3] & 0x0F) << 8) | buf[i+4]); if (ctx->PIDs_programs[elementary_PID]==NULL) { ctx->PIDs_programs[elementary_PID]=(struct PMT_entry *) malloc (sizeof (struct PMT_entry)); if (ctx->PIDs_programs[elementary_PID]==NULL) fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory to process PMT."); } ctx->PIDs_programs[elementary_PID]->elementary_PID=elementary_PID; ctx->PIDs_programs[elementary_PID]->stream_type = stream_type; ctx->PIDs_programs[elementary_PID]->program_number=program_number; ctx->PIDs_programs[elementary_PID]->printable_stream_type=get_printable_stream_type (stream_type); dbg_print(CCX_DMT_PMT, "%6u | %3X (%3u) | %s\n",elementary_PID,stream_type,stream_type, desc[ctx->PIDs_programs[elementary_PID]->printable_stream_type]); process_ccx_mpeg_descriptor (buf+i+5,ES_info_length); i += ES_info_length; } dbg_print(CCX_DMT_PMT, "---\n"); dbg_print(CCX_DMT_VERBOSE, "\nProgram map section (PMT)\n"); for (unsigned i=0; i < stream_data && (i+4)<len; i+=5) { enum ccx_stream_type stream_type = buf[i]; unsigned elementary_PID = (((buf[i+1] & 0x1F) << 8) | buf[i+2]); unsigned ES_info_length = (((buf[i+3] & 0x0F) << 8) | buf[i+4]); if (!ccx_options.print_file_reports || stream_type != CCX_STREAM_TYPE_PRIVATE_MPEG2 || !ES_info_length) { i += ES_info_length; continue; } unsigned char *es_info = buf + i + 5; for (desc_len = 0;(buf + i + 5 + ES_info_length) > es_info; es_info += desc_len) { enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++); desc_len = (*es_info++); if(descriptor_tag == CCX_MPEG_DSC_DVB_SUBTITLE) { int k = 0; for (int j = 0; j < SUB_STREAMS_CNT; j++) { if (ctx->freport.dvb_sub_pid[j] == 0) k = j; if (ctx->freport.dvb_sub_pid[j] == elementary_PID) { k = j; break; } } ctx->freport.dvb_sub_pid[k] = elementary_PID; } if(IS_VALID_TELETEXT_DESC(descriptor_tag)) { int k = 0; for (int j = 0; j < SUB_STREAMS_CNT; j++) { if (ctx->freport.tlt_sub_pid[j] == 0) k = j; if (ctx->freport.tlt_sub_pid[j] == elementary_PID) { k = j; break; } } ctx->freport.tlt_sub_pid[k] = elementary_PID; } } i += ES_info_length; } for( unsigned i=0; i < stream_data && (i+4)<len; i+=5) { enum ccx_stream_type stream_type = buf[i]; unsigned elementary_PID = (((buf[i+1] & 0x1F) << 8) | buf[i+2]); unsigned ES_info_length = (((buf[i+3] & 0x0F) << 8) | buf[i+4]); if(stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2 && ES_info_length ) { unsigned char *es_info = buf + i + 5; for (desc_len = 0;(buf + i + 5 + ES_info_length) > es_info ;es_info += desc_len) { void *ptr; enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++); desc_len = (*es_info++); if(CCX_MPEG_DESC_DATA_COMP == descriptor_tag) { int16_t component_id = 0; if(!IS_FEASIBLE(ctx->codec, ctx->nocodec, CCX_CODEC_ISDB_CC)) continue; if (desc_len < 2) break; component_id = RB16(es_info); if (component_id != 0x08) break; mprint ("*****ISDB subtitles detected\n"); ptr = init_isdb_decoder(); if (ptr == NULL) break; update_capinfo(ctx, elementary_PID, stream_type, CCX_CODEC_ISDB_CC, program_number, ptr); } if(CCX_MPEG_DSC_DVB_SUBTITLE == descriptor_tag) { struct dvb_config cnf; #ifndef ENABLE_OCR if(ccx_options.write_format != CCX_OF_SPUPNG) { mprint ("DVB subtitles detected, OCR subsystem not present. Use -out=spupng for graphic output\n"); continue; } #endif if (!IS_FEASIBLE(ctx->codec, ctx->nocodec, CCX_CODEC_DVB)) continue; memset((void*)&cnf,0,sizeof(struct dvb_config)); ret = parse_dvb_description(&cnf,es_info,desc_len); if(ret < 0) break; ptr = dvbsub_init_decoder(&cnf); if (ptr == NULL) break; update_capinfo(ctx, elementary_PID, stream_type, CCX_CODEC_DVB, program_number, ptr); max_dif = 30; } } } else if(stream_type == CCX_STREAM_TYPE_PRIVATE_USER_MPEG2 && ES_info_length ) { //if this any generally used video stream tyoe get clashed with ATSC/SCTE standard //then this code can go in some atsc flag unsigned char *es_info = buf + i + 5; for (desc_len = 0;(buf + i + 5 + ES_info_length) > es_info ;es_info += desc_len) { enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++); int nb_service; int is_608; int ser_i; desc_len = (*es_info++); if (CCX_MPEG_DSC_CAPTION_SERVICE == descriptor_tag) { nb_service = es_info[0] & 0x1f; for (ser_i = 0; ser_i < nb_service; ser_i++) { dbg_print(CCX_DMT_PMT, "CC SERVICE %d: language (%c%c%c)", nb_service, es_info[1], es_info[2], es_info[3]); is_608 = es_info[4] >> 7; dbg_print(CCX_DMT_PMT, "%s", is_608?" CEA-608":" CEA-708"); dbg_print(CCX_DMT_PMT, "%s", is_608?" CEA-608":" CEA-708"); } } update_capinfo(ctx, elementary_PID, stream_type, CCX_CODEC_ATSC_CC, program_number, NULL); } }