Hi,List I found BB is a great project,and I want to study it. In my test network without encryption, I test the burst_id with dsp patch to capture the SMS, and also ,I patch the ccch_scan to capture the voice,but I met a few difficulty, but the amr voice file seems not good, I found it hard to find the error, anyone can help me? Thanks! the patch is following:
static struct { int has_si1; int has_si3; int ccch_mode; int neci; int sys_count;
enum dch_state_t dch_state; uint8_t dch_nr; int dch_badcnt; int dch_ciph;
FILE * fh;
sbit_t bursts_dl[116 * 4]; sbit_t bursts_ul[116 * 4]; sbit_t bursts_ccch[4][116*4]; sbit_t mI[8][114];
struct gsm_sysinfo_freq cell_arfcns[1024];
uint8_t kc[8]; } app_state;
static char * void layer3_rx_burst(struct osmocom_ms *ms, struct msgb *msg) { struct l1ctl_burst_ind *bi; int16_t rx_dbm; uint16_t arfcn; int ul,do_rel=0;
/* Header handling */ bi = (struct l1ctl_burst_ind *) msg->l1h;
arfcn = ntohs(bi->band_arfcn); rx_dbm = rxlev2dbm(bi->rx_level); ul = !!(arfcn & ARFCN_UPLINK);
if (app_state.dch_state == DCH_NONE) local_ccch_burst_decode(bi,ms); /* Check for channel start */ if (app_state.dch_state == DCH_WAIT_EST) { if (bi->chan_nr == app_state.dch_nr) { if (bi->snr > 64) { /* Change state */ app_state.dch_state = DCH_ACTIVE; app_state.dch_badcnt = 0;
/* Open output */ //app_state.fh = fopen(gen_filename(ms, bi), "wb"); } else { /* Abandon ? */ do_rel = (app_state.dch_badcnt++) >= 4; } } }
/* Check for channel end */ if (app_state.dch_state == DCH_ACTIVE) { if (!ul) { /* Bad burst counting */ if (bi->snr < 64) { app_state.dch_badcnt++; printf("sdcch app_state.dch_badcnt++\n"); } else if (app_state.dch_badcnt >= 2) app_state.dch_badcnt -= 2; else app_state.dch_badcnt = 0;
/* Release condition */ do_rel = app_state.dch_badcnt >= 6; } }
// when in TCH mode, we only measure the SACCH to kown the link quanlity if (app_state.dch_state == DCH_TCH) { //printf("app_state.dch_state == DCH_TCH\n"); if (!ul && (bi->flags & BI_FLG_SACCH)) { //printf("TCH SACCH\n"); /* Bad burst counting */ if (bi->snr < 40) { app_state.dch_badcnt++; printf("sacch app_state.dch_badcnt++\n"); } else if (app_state.dch_badcnt >= 2) app_state.dch_badcnt -= 2; else app_state.dch_badcnt = 0;
/* Release condition */ do_rel = app_state.dch_badcnt >= 6; } }
/* Release ? */ if (do_rel) { printf("The Delicate Channel is released because of bad SNR!\n"); /* L1 release */ l1ctl_tx_dm_rel_req(ms); l1ctl_tx_fbsb_req(ms, ms->test_arfcn, L1CTL_FBSB_F_FB01SB, 100, 0, app_state.ccch_mode);
/* Change state */ app_state.dch_state = DCH_WAIT_REL; app_state.dch_badcnt = 0; app_state.dch_ciph = 0;
/* Close output */ if (app_state.fh) { fclose(app_state.fh); app_state.fh = NULL; } }
/* Save the burst */ if (app_state.dch_state == DCH_ACTIVE || app_state.dch_state == DCH_TCH) //fwrite(bi, sizeof(*bi), 1, app_state.fh);
/* Try local decoding */ if (!ul && (app_state.dch_state == DCH_ACTIVE || app_state.dch_state == DCH_TCH)) local_burst_decode(ms,bi); }
static void local_burst_decode(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi) { int16_t rx_dbm; uint16_t arfcn; uint32_t fn; uint8_t cbits, tn, lch_idx; int ul, bid, i, d_tch_mode; sbit_t *bursts; ubit_t bt[116];
/* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */ arfcn = ntohs(bi->band_arfcn); rx_dbm = rxlev2dbm(bi->rx_level);
fn = ntohl(bi->frame_nr); ul = !!(arfcn & ARFCN_UPLINK); bursts = ul ? app_state.bursts_ul : app_state.bursts_dl;
cbits = bi->chan_nr >> 3; tn = bi->chan_nr & 7;
bid = -1;
if (cbits == 0x01) { /* TCH/F */ lch_idx = 0; if (bi->flags & BI_FLG_SACCH) { uint32_t fn_report; fn_report = (fn - (tn * 13) + 104) % 104; bid = (fn_report - 12) / 26; printf(" SACCH fn = %d fn_report = %d\n",fn,fn_report); }else{ //printf(" TCH/F \n"); process_tch_f(ms,bi); } } else if ((cbits & 0x1e) == 0x02) { /* TCH/H */ lch_idx = cbits & 1; if (bi->flags & BI_FLG_SACCH) { uint32_t fn_report; uint8_t tn_report = (tn & ~1) | lch_idx; fn_report = (fn - (tn_report * 13) + 104) % 104; bid = (fn_report - 12) / 26; } } else if ((cbits & 0x1c) == 0x04) { /* SDCCH/4 */ lch_idx = cbits & 3; bid = bi->flags & 3; printf(" SDCCH/4\n"); } else if ((cbits & 0x18) == 0x08) { /* SDCCH/8 */ lch_idx = cbits & 7; bid = bi->flags & 3; //printf(" SDCCH/8\n"); }
if (bid == -1) return;
/* Clear if new set */ if (bid == 0) memset(bursts, 0x00, 116 * 4);
/* Unpack (ignore hu/hl) */ osmo_pbit2ubit_ext(bt, 0, bi->bits, 0, 57, 0); osmo_pbit2ubit_ext(bt, 59, bi->bits, 57, 57, 0); bt[57] = bt[58] = 1;
/* A5/x */ if (app_state.dch_ciph) { ubit_t ks_dl[114], ks_ul[114], *ks = ul ? ks_ul : ks_dl; osmo_a5(app_state.dch_ciph, app_state.kc, fn, ks_dl, ks_ul); for (i= 0; i< 57; i++) bt[i] ^= ks[i]; for (i=59; i<116; i++) bt[i] ^= ks[i-2]; }
/* Convert to softbits */ for (i=0; i<116; i++) bursts[(116*bid)+i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);
/* If last, decode */ if (bid == 3) { uint8_t l2[23]; int rv,i; struct gsm48_ass_cmd *ia; uint8_t ch_type, ch_subch, ch_ts; uint8_t chan_req_val, chan_req_mask, ra;
rv = xcch_decode(l2, bursts);
if((l2[0] == 0x03) && (l2[4] == 0x2e)) { ia =(struct gsm48_ass_cmd *)&l2[5];
rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts); //l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED); printf("Jump to TCH Channel\n");
d_tch_mode = GSM48_CMODE_SPEECH_EFR; /* open speech file and configure d_tch_decoders */ switch (d_tch_mode) {
case GSM48_CMODE_SPEECH_V1: d_speech_file = fopen( "speech.au.gsm", "wb" ); break;
case GSM48_CMODE_SPEECH_EFR: d_speech_file = fopen( gen_filename(ms,bi), "wb" ); fwrite(amr_nb_magic, 1, 6, d_speech_file); /* Write header */ break;
default: d_speech_file = NULL;
} app_state.dch_state = DCH_TCH;
if (!ia->chan_desc.h0.h) { /* Non-hopping */ uint16_t arfcn;
arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
LOGP(DRR, LOGL_NOTICE, "ASS CMD(chan_nr=0x%02x, " "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ", ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch, ia->chan_desc.h0.tsc);
/* request L1 to go to dedicated mode on assigned channel */ rv = l1ctl_tx_dm_est_req_h0(ms, arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc, GSM48_CMODE_SPEECH_EFR, 0); } #ifdef TCH_HOPPING else { /* Hopping is not support now! */ uint8_t maio, hsn, ma_len; uint16_t ma[64], arfcn; int i, j, k;
hsn = ia->chan_desc.h1.hsn; maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2);
LOGP(DRR, LOGL_NOTICE, "ASS CMD( chan_nr=0x%02x, " "HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ", ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch, ia->chan_desc.h1.tsc);
/* decode mobile allocation */ ma_len = 0; for (i=1, j=0; i<=1024; i++) { arfcn = i & 1023; if (app_state.cell_arfcns[arfcn].mask & 0x01) { k = ia->mob_alloc_len - (j>>3) - 1; if (ia->mob_alloc[k] & (1 << (j&7))) { ma[ma_len++] = arfcn; } j++; } }
/* request L1 to go to dedicated mode on assigned channel */ rv = l1ctl_tx_dm_est_req_h1(ms, maio, hsn, ma, ma_len, ia->chan_desc.chan_nr, ia->chan_desc.h1.tsc, GSM48_CMODE_SPEECH_EFR, 0); } #endif }
if (rv == 0) { uint8_t chan_type, chan_ts, chan_ss; uint8_t gsmtap_chan_type;
/* Send to GSMTAP */ rsl_dec_chan_nr(bi->chan_nr, &chan_type, &chan_ss, &chan_ts); gsmtap_chan_type = chantype_rsl2gsmtap( chan_type, bi->flags & BI_FLG_SACCH ? 0x40 : 0x00 ); gsmtap_send(gsmtap_inst, arfcn, chan_ts, gsmtap_chan_type, chan_ss, ntohl(bi->frame_nr), bi->rx_level, bi->snr, l2, sizeof(l2) );
/* Crude CIPH.MOD.COMMAND detect */ if ((l2[3] == 0x06) && (l2[4] == 0x35) && (l2[5] & 1)) app_state.dch_ciph = 1 + ((l2[5] >> 1) & 7); } } }
void tch_deinterleave(ubit_t *mC, int blockOffset) { int k; for (k = 0; k < 456; k++) { int B = ( k + blockOffset ) % 8; int j = 2 * ((49 * k) % 57) + ((k % 8) / 4); mC[k] = app_state.mI[B][j]; app_state.mI[B][j] = 0; //OBJDCOUT("deinterleave k="<<k<<" B="<<B<<" j="<<j); } }
void tch_unmap(const uint16_t *map, size_t mapSize, ubit_t * dest, ubit_t * soure) { unsigned int i; for(i=0; i<mapSize; i++) { dest[map[i]] = soure[i]; } }
void tch_map(const uint16_t *map, size_t mapSize, ubit_t * dest, ubit_t * soure) { unsigned int i; for(i=0; i<mapSize; i++) { dest[i] = soure[map[i]]; } }
void fillField(ubit_t *mStart, size_t writeIndex, uint64_t value, unsigned length) { char *dpBase = mStart + writeIndex; char *dp = dpBase + length - 1;
while (dp>=dpBase) { *dp-- = value & 0x01; value >>= 1; } }
uint64_t count_tch = 0;
static void process_tch_f(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi) { int16_t rx_dbm; uint16_t arfcn; uint32_t fn,B; uint8_t cbits, tn, lch_idx; int ul, bid, i, k, length; sbit_t *bursts, mC[456]; ubit_t bt[114],convu[189],convd[189],tch_raw[260],TCHW[260],EFRBits[244],EFRAMR[8 + 244];
pbit_t voice[33]; /* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */ arfcn = ntohs(bi->band_arfcn); rx_dbm = rxlev2dbm(bi->rx_level);
fn = ntohl(bi->frame_nr); ul = !!(arfcn & ARFCN_UPLINK);
cbits = bi->chan_nr >> 3; tn = bi->chan_nr & 7;
B = -1;
B = count_tch % 8;
if (B == -1) return;
/* Clear if new set */ if (B == 0){ for(i=0; i<4; i++){ memset(app_state.mI[i], 0x00, 114); } }else if(B == 4){ for(i=4; i<8; i++){ memset(app_state.mI[i], 0x00, 114); } }
/* Unpack (ignore hu/hl) */ osmo_pbit2ubit_ext(bt, 0, bi->bits, 0, 57, 0); osmo_pbit2ubit_ext(bt, 57, bi->bits, 57, 57, 0);
/* Convert to softbits */ for (i=0; i<114; i++) app_state.mI[B][i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);
count_tch++; // Deinterleave according to the diagonal "phase" of B. // See GSM 05.03 3.1.3. // Deinterleaves i[] to c[] if((B % 4 ==3)&&(count_tch >= 7)){ if(B == 3) { tch_deinterleave(mC, 4); }else{ tch_deinterleave(mC, 0); }
for (k = 0; k < 78; k++) { tch_raw[182 + k] = mC[378 +k]; }
osmo_conv_decode(&conv_tch_afs_12_2, mC, convu);
// 3.1.2.1 // copy class 1 bits u[] to d[] for (k = 0; k <= 90; k++) { convd[2*k] = convu[k]; convd[2*k+1] = convu[184-k]; }
memcpy(tch_raw,convd,182); // the last 78 bit has been stored!
//now only process EFR or AMR 12_2, fix me! tch_unmap(gsm660_bitorder, 260, TCHW, tch_raw);
// Remove repeating bits and CRC to get raw EFR frame (244 bits) for (k=0; k<71; k++) EFRBits[k] = TCHW[k] & 1;
for (k=73; k<123; k++) EFRBits[k-2] = TCHW[k] & 1;
for (k=125; k<178; k++) EFRBits[k-4] = TCHW[k] & 1;
for (k=180; k<230; k++) EFRBits[k-6] = TCHW[k] & 1;
for (k=232; k<252; k++) EFRBits[k-8] = TCHW[k] & 1;
// Map bits as AMR 12.2k tch_map(gsm690_12_2_bitorder, 244, EFRAMR + 8,EFRBits);
// Put the whole frame (hdr + payload) //mVFrameAMR.pack(mPrevGoodFrame); //mPrevGoodFrameLength = 32; fillField(EFRAMR, 0, 0x3c, 8); voice[32] = 0; length = osmo_ubit2pbit(voice, EFRAMR, 8 + 244); fwrite(voice, 1, 32, d_speech_file); }
}
Hi Bob,
On Mon, Jun 18, 2012 at 04:32:52PM +0800, bob wisebob wrote:
the patch is following: [...]
whatever you sent in your message, it was not a patch.
If you would like to see anyone testing/using your code at all, then at least you should be sending an unified diff (diff -u) to this list.
Regards, Harald
I have done it, This my pacth for burst_id but it can`t work well for TCH decode! http://baseband-devel.722152.n3.nabble.com/file/n4025078/app_ccch_scan.patch app_ccch_scan.patch
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
Hello..
I wanted to make some testing with your patch...When I apply your patch. I get the following error..
src/host/layer23/src/misc/app_ccch_scan.patch:28: trailing whitespace. int neci; src/host/layer23/src/misc/app_ccch_scan.patch:30: trailing whitespace.
fatal: corrupt patch at line 34
What could be the mistake.....
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
I made it by hand (copy&paste) but I missed codec.c and conv_tch_afs_12_2. With codec.c from osmocom/codec/ and the asf tables from http://baseband-devel.722152.n3.nabble.com/libosmocore-viterbi-decoder-td286... http://baseband-devel.722152.n3.nabble.com/libosmocore-viterbi-decoder-td286... the compilation was ok.
I've found some deeper infos about asf @ http://fossies.org/dox/hxplay-11.0.0/amrdump_8cpp_source.html http://fossies.org/dox/hxplay-11.0.0/amrdump_8cpp_source.html .
In osmocom-bb we have a dummy burst indicator (bi->flags & BI_FLG_DUMMY). I think, these bursts have to be filtered.
Perhaps its easier to begin with FR, because with the sample from https://srlabs.de/airprobe-how-to/ we have FR and with osmocom-bb (mobile_app) and old Nokias ( http://www.panuworld.net/nuukiaworld/misc/netmon/tests.htm http://www.panuworld.net/nuukiaworld/misc/netmon/tests.htm ) EFR can be disabled to get FR.
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
Dear Bob,
On Mon, Jun 18, 2012 at 04:38:55AM -0700, bob wrote:
I have done it, This my pacth for burst_id but it can`t work well for TCH decode! http://baseband-devel.722152.n3.nabble.com/file/n4025078/app_ccch_scan.patch app_ccch_scan.patch
you still hve not sent the actual patch to this mailing list.
I would appreciate if you could follow common procedures / habits of FOSS projects and send your patches as unified diff to the mailing list for review / comments.
Linking code published on a website that is not even online for one month is very inefficient. Now people can still read your mails in the archvie but not your patch. What a waste!
Regards, Harald
I think the key importance is the codec mode indication of AMR, in my test network, the channel mode is speed full rate and half rate version 3; anyone familiar with it?
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
I want to compare the decoding with airprobe. For this I need a gsm-receiver cfile with EFR data. Does someone have such a file?
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
Hi, lonelysurfer: the website https://srlabs.de/airprobe-how-to/ has a sample, but the version of speech codec is 1,so there are much defferent in decode the voice if your network is AMR speech codec, so there are much work to do,I think we must read GSM5.09 about AMR firstly. I am very happy to work with you about the AMR.
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
AMR codec is said to have a 1 byte header. AMR run at various bitrate 4.75, 5.15, 5.90, 6.70, 7.40, 7.95, 10.2 or 12.2 kbit/s and each bitrate provide different sized output blocks of 95, 103, 118, 134, 148, 159, 204, and 244 bits.
In the 1 byte header it's written which is the encoding bitrate of the specific AMR 20ms encoded audio sample. In particular the top 4 bits tell the bitrate (CMR) while the lower bits are reserved and not used (all 0 or all 1).
*CMR* * MODE* *FRAME SIZE( in bytes )* 0 AMR 4.75 13 1 AMR 5.15 14 2 AMR 5.9 16 3 AMR 6.7 18 4 AMR 7.4 20 5 AMR 7.95 21 6 AMR 10.2 27 7 AMR 12.2 32
AMR Reference: http://wiki.forum.nokia.com/index.php/AMR_format http://wiki.forum.nokia.com/index.php/AMR_format http://en.wikipedia.org/wiki/Adaptive_Multi-Rate_audio_codec http://en.wikipedia.org/wiki/Adaptive_Multi-Rate_audio_codec
-- View this message in context: http://baseband-devel.722152.n3.nabble.com/my-patch-for-decode-using-burst-i... Sent from the baseband-devel mailing list archive at Nabble.com.
baseband-devel@lists.osmocom.org