intial checkin of the libosmocore project
This commit is contained in:
commit
ec8b4501c7
|
@ -0,0 +1,23 @@
|
|||
Makefile
|
||||
.deps
|
||||
.libs
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.in
|
||||
*.am
|
||||
*.pc
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.h*
|
||||
config.sub
|
||||
config.log
|
||||
config.status
|
||||
config.guess
|
||||
configure
|
||||
depcomp
|
||||
missing
|
||||
ltmain.sh
|
||||
install-sh
|
||||
stamp-h1
|
||||
libtool
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef _BITVEC_H
|
||||
#define _BITVEC_H
|
||||
|
||||
/* bit vector utility routines */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are
|
||||
* defined relative to the 0x2b padding pattern */
|
||||
enum bit_value {
|
||||
ZERO = 0,
|
||||
ONE = 1,
|
||||
L = 2,
|
||||
H = 3,
|
||||
};
|
||||
|
||||
struct bitvec {
|
||||
unsigned int cur_bit; /* curser to the next unused bit */
|
||||
unsigned int data_len; /* length of data array in bytes */
|
||||
uint8_t *data; /* pointer to data array */
|
||||
};
|
||||
|
||||
/* check if the bit is 0 or 1 for a given position inside a bitvec */
|
||||
enum bit_value bitvec_get_bit_pos(struct bitvec *bv, unsigned int bitnr);
|
||||
|
||||
/* get the Nth set bit inside the bit vector */
|
||||
unsigned int bitvec_get_nth_set_bit(struct bitvec *bv, unsigned int n);
|
||||
|
||||
/* Set a bit at given position */
|
||||
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
|
||||
enum bit_value bit);
|
||||
|
||||
/* Set the next bit in the vector */
|
||||
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
|
||||
|
||||
/* Set multiple bits at the current position */
|
||||
int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
|
||||
|
||||
/* Add an unsigned integer (of length count bits) to current position */
|
||||
int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
|
||||
|
||||
|
||||
/* Pad the bit vector up to a certain bit position */
|
||||
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
|
||||
|
||||
#endif /* _BITVEC_H */
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* COMP128 header
|
||||
*
|
||||
* See comp128.c for details
|
||||
*/
|
||||
|
||||
#ifndef __COMP128_H__
|
||||
#define __COMP128_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Performs the COMP128 algorithm (used as A3/A8)
|
||||
* ki : uint8_t [16]
|
||||
* srand : uint8_t [16]
|
||||
* sres : uint8_t [4]
|
||||
* kc : uint8_t [8]
|
||||
*/
|
||||
void comp128(uint8_t *ki, uint8_t *srand, uint8_t *sres, uint8_t *kc);
|
||||
|
||||
#endif /* __COMP128_H__ */
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* GSM utility functions, e.g. coding and decoding */
|
||||
/*
|
||||
* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GSM_UTILS_H
|
||||
#define GSM_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum gsm_band {
|
||||
GSM_BAND_850 = 1,
|
||||
GSM_BAND_900 = 2,
|
||||
GSM_BAND_1800 = 4,
|
||||
GSM_BAND_1900 = 8,
|
||||
GSM_BAND_450 = 0x10,
|
||||
GSM_BAND_480 = 0x20,
|
||||
GSM_BAND_750 = 0x40,
|
||||
GSM_BAND_810 = 0x80,
|
||||
};
|
||||
|
||||
int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length);
|
||||
int gsm_7bit_encode(uint8_t *result, const char *data);
|
||||
|
||||
int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm);
|
||||
int ms_pwr_dbm(enum gsm_band band, uint8_t lvl);
|
||||
|
||||
/* According to TS 08.05 Chapter 8.1.4 */
|
||||
int rxlev2dbm(uint8_t rxlev);
|
||||
uint8_t dbm2rxlev(int dbm);
|
||||
|
||||
/* According to GSM 04.08 Chapter 10.5.2.29 */
|
||||
static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; }
|
||||
static inline int rach_max_trans_raw2val(int raw) {
|
||||
const int tbl[4] = { 1, 2, 4, 7 };
|
||||
return tbl[raw & 3];
|
||||
}
|
||||
|
||||
void generate_backtrace();
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef _GSMTAP_H
|
||||
#define _GSMTAP_H
|
||||
|
||||
/* gsmtap header, pseudo-header in front of the actua GSM payload*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define GSMTAP_VERSION 0x01
|
||||
|
||||
#define GSMTAP_TYPE_UM 0x01
|
||||
#define GSMTAP_TYPE_ABIS 0x02
|
||||
#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */
|
||||
|
||||
#define GSMTAP_BURST_UNKNOWN 0x00
|
||||
#define GSMTAP_BURST_FCCH 0x01
|
||||
#define GSMTAP_BURST_PARTIAL_SCH 0x02
|
||||
#define GSMTAP_BURST_SCH 0x03
|
||||
#define GSMTAP_BURST_CTS_SCH 0x04
|
||||
#define GSMTAP_BURST_COMPACT_SCH 0x05
|
||||
#define GSMTAP_BURST_NORMAL 0x06
|
||||
#define GSMTAP_BURST_DUMMY 0x07
|
||||
#define GSMTAP_BURST_ACCESS 0x08
|
||||
#define GSMTAP_BURST_NONE 0x09
|
||||
|
||||
#define GSMTAP_UDP_PORT 4729
|
||||
|
||||
struct gsmtap_hdr {
|
||||
uint8_t version; /* version, set to 0x01 currently */
|
||||
uint8_t hdr_len; /* length in number of 32bit words */
|
||||
uint8_t type; /* see GSMTAP_TYPE_* */
|
||||
uint8_t timeslot; /* timeslot (0..7 on Um) */
|
||||
|
||||
uint16_t arfcn; /* ARFCN (frequency) */
|
||||
uint8_t noise_db; /* noise figure in dB */
|
||||
uint8_t signal_db; /* signal level in dB */
|
||||
|
||||
uint32_t frame_number; /* GSM Frame Number (FN) */
|
||||
|
||||
uint8_t burst_type; /* Type of burst, see above */
|
||||
uint8_t antenna_nr; /* Antenna Number */
|
||||
uint16_t res; /* reserved for future use (RFU) */
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/* PCAP related definitions */
|
||||
#define TCPDUMP_MAGIC 0xa1b2c3d4
|
||||
#ifndef LINKTYPE_GSMTAP
|
||||
#define LINKTYPE_GSMTAP 2342
|
||||
#endif
|
||||
struct pcap_timeval {
|
||||
int32_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
};
|
||||
|
||||
struct pcap_sf_pkthdr {
|
||||
struct pcap_timeval ts; /* time stamp */
|
||||
uint32_t caplen; /* lenght of portion present */
|
||||
uint32_t len; /* length of this packet */
|
||||
};
|
||||
|
||||
#endif /* _GSMTAP_H */
|
|
@ -0,0 +1,360 @@
|
|||
#ifndef _LINUX_LLIST_H
|
||||
#define _LINUX_LLIST_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef inline
|
||||
#define inline __inline__
|
||||
#endif
|
||||
|
||||
static inline void prefetch(const void *x) {;}
|
||||
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
*
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type, member) );})
|
||||
|
||||
|
||||
/*
|
||||
* These are non-NULL pointers that will result in page faults
|
||||
* under normal circumstances, used to verify that nobody uses
|
||||
* non-initialized llist entries.
|
||||
*/
|
||||
#define LLIST_POISON1 ((void *) 0x00100100)
|
||||
#define LLIST_POISON2 ((void *) 0x00200200)
|
||||
|
||||
/*
|
||||
* Simple doubly linked llist implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole llists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct llist_head {
|
||||
struct llist_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LLIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LLIST_HEAD(name) \
|
||||
struct llist_head name = LLIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LLIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal llist manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __llist_add(struct llist_head *_new,
|
||||
struct llist_head *prev,
|
||||
struct llist_head *next)
|
||||
{
|
||||
next->prev = _new;
|
||||
_new->next = next;
|
||||
_new->prev = prev;
|
||||
prev->next = _new;
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: llist head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void llist_add(struct llist_head *_new, struct llist_head *head)
|
||||
{
|
||||
__llist_add(_new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: llist head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head)
|
||||
{
|
||||
__llist_add(_new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a llist entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal llist manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_del - deletes entry from llist.
|
||||
* @entry: the element to delete from the llist.
|
||||
* Note: llist_empty on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static inline void llist_del(struct llist_head *entry)
|
||||
{
|
||||
__llist_del(entry->prev, entry->next);
|
||||
entry->next = (struct llist_head *)LLIST_POISON1;
|
||||
entry->prev = (struct llist_head *)LLIST_POISON2;
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_del_init - deletes entry from llist and reinitialize it.
|
||||
* @entry: the element to delete from the llist.
|
||||
*/
|
||||
static inline void llist_del_init(struct llist_head *entry)
|
||||
{
|
||||
__llist_del(entry->prev, entry->next);
|
||||
INIT_LLIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_move - delete from one llist and add as another's head
|
||||
* @llist: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void llist_move(struct llist_head *llist, struct llist_head *head)
|
||||
{
|
||||
__llist_del(llist->prev, llist->next);
|
||||
llist_add(llist, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_move_tail - delete from one llist and add as another's tail
|
||||
* @llist: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void llist_move_tail(struct llist_head *llist,
|
||||
struct llist_head *head)
|
||||
{
|
||||
__llist_del(llist->prev, llist->next);
|
||||
llist_add_tail(llist, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_empty - tests whether a llist is empty
|
||||
* @head: the llist to test.
|
||||
*/
|
||||
static inline int llist_empty(const struct llist_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __llist_splice(struct llist_head *llist,
|
||||
struct llist_head *head)
|
||||
{
|
||||
struct llist_head *first = llist->next;
|
||||
struct llist_head *last = llist->prev;
|
||||
struct llist_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_splice - join two llists
|
||||
* @llist: the new llist to add.
|
||||
* @head: the place to add it in the first llist.
|
||||
*/
|
||||
static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
|
||||
{
|
||||
if (!llist_empty(llist))
|
||||
__llist_splice(llist, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_splice_init - join two llists and reinitialise the emptied llist.
|
||||
* @llist: the new llist to add.
|
||||
* @head: the place to add it in the first llist.
|
||||
*
|
||||
* The llist at @llist is reinitialised
|
||||
*/
|
||||
static inline void llist_splice_init(struct llist_head *llist,
|
||||
struct llist_head *head)
|
||||
{
|
||||
if (!llist_empty(llist)) {
|
||||
__llist_splice(llist, head);
|
||||
INIT_LLIST_HEAD(llist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* llist_entry - get the struct for this entry
|
||||
* @ptr: the &struct llist_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the llist_struct within the struct.
|
||||
*/
|
||||
#define llist_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* llist_for_each - iterate over a llist
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
*/
|
||||
#define llist_for_each(pos, head) \
|
||||
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
||||
pos = pos->next, prefetch(pos->next))
|
||||
|
||||
/**
|
||||
* __llist_for_each - iterate over a llist
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
*
|
||||
* This variant differs from llist_for_each() in that it's the
|
||||
* simplest possible llist iteration code, no prefetching is done.
|
||||
* Use this for code that knows the llist to be very short (empty
|
||||
* or 1 entry) most of the time.
|
||||
*/
|
||||
#define __llist_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* llist_for_each_prev - iterate over a llist backwards
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
*/
|
||||
#define llist_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
|
||||
pos = pos->prev, prefetch(pos->prev))
|
||||
|
||||
/**
|
||||
* llist_for_each_safe - iterate over a llist safe against removal of llist entry
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @n: another &struct llist_head to use as temporary storage
|
||||
* @head: the head for your llist.
|
||||
*/
|
||||
#define llist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* llist_for_each_entry - iterate over llist of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
* @member: the name of the llist_struct within the struct.
|
||||
*/
|
||||
#define llist_for_each_entry(pos, head, member) \
|
||||
for (pos = llist_entry((head)->next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = llist_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
/**
|
||||
* llist_for_each_entry_reverse - iterate backwards over llist of given type.
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
* @member: the name of the llist_struct within the struct.
|
||||
*/
|
||||
#define llist_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = llist_entry((head)->prev, typeof(*pos), member), \
|
||||
prefetch(pos->member.prev); \
|
||||
&pos->member != (head); \
|
||||
pos = llist_entry(pos->member.prev, typeof(*pos), member), \
|
||||
prefetch(pos->member.prev))
|
||||
|
||||
/**
|
||||
* llist_for_each_entry_continue - iterate over llist of given type
|
||||
* continuing after existing point
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
* @member: the name of the llist_struct within the struct.
|
||||
*/
|
||||
#define llist_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = llist_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
/**
|
||||
* llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your llist.
|
||||
* @member: the name of the llist_struct within the struct.
|
||||
*/
|
||||
#define llist_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = llist_entry((head)->next, typeof(*pos), member), \
|
||||
n = llist_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = llist_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* llist_for_each_rcu - iterate over an rcu-protected llist
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
*/
|
||||
#define llist_for_each_rcu(pos, head) \
|
||||
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
||||
pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
|
||||
|
||||
#define __llist_for_each_rcu(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
|
||||
|
||||
/**
|
||||
* llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
|
||||
* against removal of llist entry
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @n: another &struct llist_head to use as temporary storage
|
||||
* @head: the head for your llist.
|
||||
*/
|
||||
#define llist_for_each_safe_rcu(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
|
||||
|
||||
/**
|
||||
* llist_for_each_entry_rcu - iterate over rcu llist of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
* @member: the name of the llist_struct within the struct.
|
||||
*/
|
||||
#define llist_for_each_entry_rcu(pos, head, member) \
|
||||
for (pos = llist_entry((head)->next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = llist_entry(pos->member.next, typeof(*pos), member), \
|
||||
({ smp_read_barrier_depends(); 0;}), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
|
||||
/**
|
||||
* llist_for_each_continue_rcu - iterate over an rcu-protected llist
|
||||
* continuing after existing point.
|
||||
* @pos: the &struct llist_head to use as a loop counter.
|
||||
* @head: the head for your llist.
|
||||
*/
|
||||
#define llist_for_each_continue_rcu(pos, head) \
|
||||
for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
|
||||
(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,114 @@
|
|||
#ifndef _MSGB_H
|
||||
#define _MSGB_H
|
||||
|
||||
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "linuxlist.h"
|
||||
|
||||
struct bts_link;
|
||||
|
||||
struct msgb {
|
||||
struct llist_head list;
|
||||
|
||||
/* ptr to the physical E1 link to the BTS(s) */
|
||||
struct gsm_bts_link *bts_link;
|
||||
|
||||
/* Part of which TRX logical channel we were received / transmitted */
|
||||
struct gsm_bts_trx *trx;
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
unsigned char *l2h;
|
||||
unsigned char *l3h;
|
||||
unsigned char *smsh;
|
||||
|
||||
uint16_t data_len;
|
||||
uint16_t len;
|
||||
|
||||
unsigned char *head;
|
||||
unsigned char *tail;
|
||||
unsigned char *data;
|
||||
unsigned char _data[0];
|
||||
};
|
||||
|
||||
extern struct msgb *msgb_alloc(uint16_t size, const char *name);
|
||||
extern void msgb_free(struct msgb *m);
|
||||
extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
|
||||
extern struct msgb *msgb_dequeue(struct llist_head *queue);
|
||||
extern void msgb_reset(struct msgb *m);
|
||||
|
||||
#define msgb_l2(m) ((void *)(m->l2h))
|
||||
#define msgb_l3(m) ((void *)(m->l3h))
|
||||
#define msgb_sms(m) ((void *)(m->smsh))
|
||||
|
||||
static inline unsigned int msgb_l2len(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->tail - (uint8_t *)msgb_l2(msgb);
|
||||
}
|
||||
|
||||
static inline unsigned int msgb_l3len(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->tail - (uint8_t *)msgb_l3(msgb);
|
||||
}
|
||||
|
||||
static inline unsigned int msgb_headlen(const struct msgb *msgb)
|
||||
{
|
||||
return msgb->len - msgb->data_len;
|
||||
}
|
||||
static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
unsigned char *tmp = msgb->tail;
|
||||
msgb->tail += len;
|
||||
msgb->len += len;
|
||||
return tmp;
|
||||
}
|
||||
static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
msgb->data -= len;
|
||||
msgb->len += len;
|
||||
return msgb->data;
|
||||
}
|
||||
static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
|
||||
{
|
||||
msgb->len -= len;
|
||||
return msgb->data += len;
|
||||
}
|
||||
static inline int msgb_tailroom(const struct msgb *msgb)
|
||||
{
|
||||
return (msgb->data + msgb->data_len) - msgb->tail;
|
||||
}
|
||||
|
||||
/* increase the headroom of an empty msgb, reducing the tailroom */
|
||||
static inline void msgb_reserve(struct msgb *msg, int len)
|
||||
{
|
||||
msg->data += len;
|
||||
msg->tail += len;
|
||||
}
|
||||
|
||||
static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
|
||||
const char *name)
|
||||
{
|
||||
struct msgb *msg = msgb_alloc(size, name);
|
||||
if (msg)
|
||||
msgb_reserve(msg, headroom);
|
||||
return msg;
|
||||
}
|
||||
|
||||
#endif /* _MSGB_H */
|
|
@ -0,0 +1,743 @@
|
|||
#ifndef PROTO_GSM_04_08_H
|
||||
#define PROTO_GSM_04_08_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* GSM TS 04.08 definitions */
|
||||
struct gsm_lchan;
|
||||
|
||||
struct gsm48_classmark1 {
|
||||
uint8_t spare:1,
|
||||
rev_level:2,
|
||||
es_ind:1,
|
||||
a5_1:1,
|
||||
pwr_lev:3;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chapter 10.5.2.5 */
|
||||
struct gsm48_chan_desc {
|
||||
uint8_t chan_nr;
|
||||
union {
|
||||
struct {
|
||||
uint8_t maio_high:4,
|
||||
h:1,
|
||||
tsc:3;
|
||||
uint8_t hsn:6,
|
||||
maio_low:2;
|
||||
} h1;
|
||||
struct {
|
||||
uint8_t arfcn_high:2,
|
||||
spare:2,
|
||||
h:1,
|
||||
tsc:3;
|
||||
uint8_t arfcn_low;
|
||||
} h0;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chapter 10.5.2.21aa */
|
||||
struct gsm48_multi_rate_conf {
|
||||
uint8_t smod : 2,
|
||||
spare: 1,
|
||||
icmi : 1,
|
||||
nscb : 1,
|
||||
ver : 3;
|
||||
uint8_t m4_75 : 1,
|
||||
m5_15 : 1,
|
||||
m5_90 : 1,
|
||||
m6_70 : 1,
|
||||
m7_40 : 1,
|
||||
m7_95 : 1,
|
||||
m10_2 : 1,
|
||||
m12_2 : 1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Chapter 10.5.2.30 */
|
||||
struct gsm48_req_ref {
|
||||
uint8_t ra;
|
||||
uint8_t t3_high:3,
|
||||
t1_:5;
|
||||
uint8_t t2:5,
|
||||
t3_low:3;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* Chapter 9.1.5/9.1.6
|
||||
*
|
||||
* For 9.1.6 the chan_desc has the meaning of 10.5.2.5a
|
||||
*/
|
||||
struct gsm48_chan_mode_modify {
|
||||
struct gsm48_chan_desc chan_desc;
|
||||
uint8_t mode;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum gsm48_chan_mode {
|
||||
GSM48_CMODE_SIGN = 0x00,
|
||||
GSM48_CMODE_SPEECH_V1 = 0x01,
|
||||
GSM48_CMODE_SPEECH_EFR = 0x21,
|
||||
GSM48_CMODE_SPEECH_AMR = 0x41,
|
||||
GSM48_CMODE_DATA_14k5 = 0x0f,
|
||||
GSM48_CMODE_DATA_12k0 = 0x03,
|
||||
GSM48_CMODE_DATA_6k0 = 0x0b,
|
||||
GSM48_CMODE_DATA_3k6 = 0x23,
|
||||
};
|
||||
|
||||
/* Chapter 9.1.2 */
|
||||
struct gsm48_ass_cmd {
|
||||
/* Semantic is from 10.5.2.5a */
|
||||
struct gsm48_chan_desc chan_desc;
|
||||
uint8_t power_command;
|
||||
uint8_t data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Chapter 10.5.2.2 */
|
||||
struct gsm48_cell_desc {
|
||||
uint8_t bcc:3,
|
||||
ncc:3,
|
||||
arfcn_hi:2;
|
||||
uint8_t arfcn_lo;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Chapter 9.1.15 */
|
||||
struct gsm48_ho_cmd {
|
||||
struct gsm48_cell_desc cell_desc;
|
||||
struct gsm48_chan_desc chan_desc;
|
||||
uint8_t ho_ref;
|
||||
uint8_t power_command;
|
||||
uint8_t data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Chapter 9.1.18 */
|
||||
struct gsm48_imm_ass {
|
||||
uint8_t l2_plen;
|
||||
uint8_t proto_discr;
|
||||
uint8_t msg_type;
|
||||
uint8_t page_mode;
|
||||
struct gsm48_chan_desc chan_desc;
|
||||
struct gsm48_req_ref req_ref;
|
||||
uint8_t timing_advance;
|
||||
uint8_t mob_alloc_len;
|
||||
uint8_t mob_alloc[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chapter 10.5.1.3 */
|
||||
struct gsm48_loc_area_id {
|
||||
uint8_t digits[3]; /* BCD! */
|
||||
uint16_t lac;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.2.2 */
|
||||
struct gsm48_auth_req {
|
||||
uint8_t key_seq:4,
|
||||
spare:4;
|
||||
uint8_t rand[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.2.15 */
|
||||
struct gsm48_loc_upd_req {
|
||||
uint8_t type:4,
|
||||
key_seq:4;
|
||||
struct gsm48_loc_area_id lai;
|
||||
struct gsm48_classmark1 classmark1;
|
||||
uint8_t mi_len;
|
||||
uint8_t mi[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 10.1 */
|
||||
struct gsm48_hdr {
|
||||
uint8_t proto_discr;
|
||||
uint8_t msg_type;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.3x System information Type header */
|
||||
struct gsm48_system_information_type_header {
|
||||
uint8_t l2_plen;
|
||||
uint8_t rr_protocol_discriminator :4,
|
||||
skip_indicator:4;
|
||||
uint8_t system_information;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm48_rach_control {
|
||||
uint8_t re :1,
|
||||
cell_bar :1,
|
||||
tx_integer :4,
|
||||
max_trans :2;
|
||||
uint8_t t2;
|
||||
uint8_t t3;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 10.5.2.4 Cell Selection Parameters */
|
||||
struct gsm48_cell_sel_par {
|
||||
uint8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */
|
||||
cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */
|
||||
uint8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */
|
||||
neci:1,
|
||||
acs:1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */
|
||||
struct gsm48_control_channel_descr {
|
||||
uint8_t ccch_conf :3,
|
||||
bs_ag_blks_res :3,
|
||||
att :1,
|
||||
spare1 :1;
|
||||
uint8_t bs_pa_mfrms : 3,
|
||||
spare2 :5;
|
||||
uint8_t t3212;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct gsm48_cell_options {
|
||||
uint8_t radio_link_timeout:4,
|
||||
dtx:2,
|
||||
pwrc:1,
|
||||
spare:1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.2.9 CM service request */
|
||||
struct gsm48_service_request {
|
||||
uint8_t cm_service_type : 4,
|
||||
cipher_key_seq : 4;
|
||||
/* length + 3 bytes */
|
||||
uint32_t classmark;
|
||||
uint8_t mi_len;
|
||||
uint8_t mi[0];
|
||||
/* optional priority level */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.31 System information Type 1 */
|
||||
struct gsm48_system_information_type_1 {
|
||||
struct gsm48_system_information_type_header header;
|
||||
uint8_t cell_channel_description[16];
|
||||
struct gsm48_rach_control rach_control;
|
||||
uint8_t rest_octets[0]; /* NCH position on the CCCH */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.32 System information Type 2 */
|
||||
struct gsm48_system_information_type_2 {
|
||||
struct gsm48_system_information_type_header header;
|
||||
uint8_t bcch_frequency_list[16];
|
||||
uint8_t ncc_permitted;
|
||||
struct gsm48_rach_control rach_control;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.35 System information Type 3 */
|
||||
struct gsm48_system_information_type_3 {
|
||||
struct gsm48_system_information_type_header header;
|
||||
uint16_t cell_identity;
|
||||
struct gsm48_loc_area_id lai;
|
||||
struct gsm48_control_channel_descr control_channel_desc;
|
||||
struct gsm48_cell_options cell_options;
|
||||
struct gsm48_cell_sel_par cell_sel_par;
|
||||
struct gsm48_rach_control rach_control;
|
||||
uint8_t rest_octets[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.36 System information Type 4 */
|
||||
struct gsm48_system_information_type_4 {
|
||||
struct gsm48_system_information_type_header header;
|
||||
struct gsm48_loc_area_id lai;
|
||||
struct gsm48_cell_sel_par cell_sel_par;
|
||||
struct gsm48_rach_control rach_control;
|
||||
/* optional CBCH conditional CBCH... followed by
|
||||
mandantory SI 4 Reset Octets
|
||||
*/
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.37 System information Type 5 */
|
||||
struct gsm48_system_information_type_5 {
|
||||
uint8_t rr_protocol_discriminator :4,
|
||||
skip_indicator:4;
|
||||
uint8_t system_information;
|
||||
uint8_t bcch_frequency_list[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.40 System information Type 6 */
|
||||
struct gsm48_system_information_type_6 {
|
||||
uint8_t rr_protocol_discriminator :4,
|
||||
skip_indicator:4;
|
||||
uint8_t system_information;
|
||||
uint16_t cell_identity;
|
||||
struct gsm48_loc_area_id lai;
|
||||
struct gsm48_cell_options cell_options;
|
||||
uint8_t ncc_permitted;
|
||||
uint8_t rest_octets[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.43a System Information type 13 */
|
||||
struct gsm48_system_information_type_13 {
|
||||
struct gsm48_system_information_type_header header;
|
||||
uint8_t rest_octets[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.2.12 IMSI Detach Indication */
|
||||
struct gsm48_imsi_detach_ind {
|
||||
struct gsm48_classmark1 classmark1;
|
||||
uint8_t mi_len;
|
||||
uint8_t mi[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 10.2 + GSM 04.07 12.2.3.1.1 */
|
||||
#define GSM48_PDISC_GROUP_CC 0x00
|
||||
#define GSM48_PDISC_BCAST_CC 0x01
|
||||
#define GSM48_PDISC_PDSS1 0x02
|
||||
#define GSM48_PDISC_CC 0x03
|
||||
#define GSM48_PDISC_PDSS2 0x04
|
||||
#define GSM48_PDISC_MM 0x05
|
||||
#define GSM48_PDISC_RR 0x06
|
||||
#define GSM48_PDISC_MM_GPRS 0x08
|
||||
#define GSM48_PDISC_SMS 0x09
|
||||
#define GSM48_PDISC_SM_GPRS 0x0a
|
||||
#define GSM48_PDISC_NC_SS 0x0b
|
||||
#define GSM48_PDISC_LOC 0x0c
|
||||
#define GSM48_PDISC_MASK 0x0f
|
||||
#define GSM48_PDISC_USSD 0x11
|
||||
|
||||
/* Section 10.4 */
|
||||
#define GSM48_MT_RR_INIT_REQ 0x3c
|
||||
#define GSM48_MT_RR_ADD_ASS 0x3b
|
||||
#define GSM48_MT_RR_IMM_ASS 0x3f
|
||||
#define GSM48_MT_RR_IMM_ASS_EXT 0x39
|
||||
#define GSM48_MT_RR_IMM_ASS_REJ 0x3a
|
||||
|
||||
#define GSM48_MT_RR_CIPH_M_CMD 0x35
|
||||
#define GSM48_MT_RR_CIPH_M_COMPL 0x32
|
||||
|
||||
#define GSM48_MT_RR_CFG_CHG_CMD 0x30
|
||||
#define GSM48_MT_RR_CFG_CHG_ACK 0x31
|
||||
#define GSM48_MT_RR_CFG_CHG_REJ 0x33
|
||||
|
||||
#define GSM48_MT_RR_ASS_CMD 0x2e
|
||||
#define GSM48_MT_RR_ASS_COMPL 0x29
|
||||
#define GSM48_MT_RR_ASS_FAIL 0x2f
|
||||
#define GSM48_MT_RR_HANDO_CMD 0x2b
|
||||
#define GSM48_MT_RR_HANDO_COMPL 0x2c
|
||||
#define GSM48_MT_RR_HANDO_FAIL 0x28
|
||||
#define GSM48_MT_RR_HANDO_INFO 0x2d
|
||||
|
||||
#define GSM48_MT_RR_CELL_CHG_ORDER 0x08
|
||||
#define GSM48_MT_RR_PDCH_ASS_CMD 0x23
|
||||
|
||||
#define GSM48_MT_RR_CHAN_REL 0x0d
|
||||
#define GSM48_MT_RR_PART_REL 0x0a
|
||||
#define GSM48_MT_RR_PART_REL_COMP 0x0f
|
||||
|
||||
#define GSM48_MT_RR_PAG_REQ_1 0x21
|
||||
#define GSM48_MT_RR_PAG_REQ_2 0x22
|
||||
#define GSM48_MT_RR_PAG_REQ_3 0x24
|
||||
#define GSM48_MT_RR_PAG_RESP 0x27
|
||||
#define GSM48_MT_RR_NOTIF_NCH 0x20
|
||||
#define GSM48_MT_RR_NOTIF_FACCH 0x25
|
||||
#define GSM48_MT_RR_NOTIF_RESP 0x26
|
||||
|
||||
#define GSM48_MT_RR_SYSINFO_8 0x18
|
||||
#define GSM48_MT_RR_SYSINFO_1 0x19
|
||||
#define GSM48_MT_RR_SYSINFO_2 0x1a
|
||||
#define GSM48_MT_RR_SYSINFO_3 0x1b
|
||||
#define GSM48_MT_RR_SYSINFO_4 0x1c
|
||||
#define GSM48_MT_RR_SYSINFO_5 0x1d
|
||||
#define GSM48_MT_RR_SYSINFO_6 0x1e
|
||||
#define GSM48_MT_RR_SYSINFO_7 0x1f
|
||||
|
||||
#define GSM48_MT_RR_SYSINFO_2bis 0x02
|
||||
#define GSM48_MT_RR_SYSINFO_2ter 0x03
|
||||
#define GSM48_MT_RR_SYSINFO_5bis 0x05
|
||||
#define GSM48_MT_RR_SYSINFO_5ter 0x06
|
||||
#define GSM48_MT_RR_SYSINFO_9 0x04
|
||||
#define GSM48_MT_RR_SYSINFO_13 0x00
|
||||
|
||||
#define GSM48_MT_RR_SYSINFO_16 0x3d
|
||||
#define GSM48_MT_RR_SYSINFO_17 0x3e
|
||||
|
||||
#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10
|
||||
#define GSM48_MT_RR_STATUS 0x12
|
||||
#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17
|
||||
#define GSM48_MT_RR_FREQ_REDEF 0x14
|
||||
#define GSM48_MT_RR_MEAS_REP 0x15
|
||||
#define GSM48_MT_RR_CLSM_CHG 0x16
|
||||
#define GSM48_MT_RR_CLSM_ENQ 0x13
|
||||
#define GSM48_MT_RR_EXT_MEAS_REP 0x36
|
||||
#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37
|
||||
#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34
|
||||
|
||||
#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08
|
||||
#define GSM48_MT_RR_UPLINK_RELEASE 0x0e
|
||||
#define GSM48_MT_RR_UPLINK_FREE 0x0c
|
||||
#define GSM48_MT_RR_UPLINK_BUSY 0x2a
|
||||
#define GSM48_MT_RR_TALKER_IND 0x11
|
||||
|
||||
#define GSM48_MT_RR_APP_INFO 0x38
|
||||
|
||||
/* Table 10.2/3GPP TS 04.08 */
|
||||
#define GSM48_MT_MM_IMSI_DETACH_IND 0x01
|
||||
#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02
|
||||
#define GSM48_MT_MM_LOC_UPD_REJECT 0x04
|
||||
#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08
|
||||
|
||||
#define GSM48_MT_MM_AUTH_REJ 0x11
|
||||
#define GSM48_MT_MM_AUTH_REQ 0x12
|
||||
#define GSM48_MT_MM_AUTH_RESP 0x14
|
||||
#define GSM48_MT_MM_ID_REQ 0x18
|
||||
#define GSM48_MT_MM_ID_RESP 0x19
|
||||
#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a
|
||||
#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b
|
||||
|
||||
#define GSM48_MT_MM_CM_SERV_ACC 0x21
|
||||
#define GSM48_MT_MM_CM_SERV_REJ 0x22
|
||||
#define GSM48_MT_MM_CM_SERV_ABORT 0x23
|
||||
#define GSM48_MT_MM_CM_SERV_REQ 0x24
|
||||
#define GSM48_MT_MM_CM_SERV_PROMPT 0x25
|
||||
#define GSM48_MT_MM_CM_REEST_REQ 0x28
|
||||
#define GSM48_MT_MM_ABORT 0x29
|
||||
|
||||
#define GSM48_MT_MM_NULL 0x30
|
||||
#define GSM48_MT_MM_STATUS 0x31
|
||||
#define GSM48_MT_MM_INFO 0x32
|
||||
|
||||
/* Table 10.3/3GPP TS 04.08 */
|
||||
#define GSM48_MT_CC_ALERTING 0x01
|
||||
#define GSM48_MT_CC_CALL_CONF 0x08
|
||||
#define GSM48_MT_CC_CALL_PROC 0x02
|
||||
#define GSM48_MT_CC_CONNECT 0x07
|
||||
#define GSM48_MT_CC_CONNECT_ACK 0x0f
|
||||
#define GSM48_MT_CC_EMERG_SETUP 0x0e
|
||||
#define GSM48_MT_CC_PROGRESS 0x03
|
||||
#define GSM48_MT_CC_ESTAB 0x04
|
||||
#define GSM48_MT_CC_ESTAB_CONF 0x06
|
||||
#define GSM48_MT_CC_RECALL 0x0b
|
||||
#define GSM48_MT_CC_START_CC 0x09
|
||||
#define GSM48_MT_CC_SETUP 0x05
|
||||
|
||||
#define GSM48_MT_CC_MODIFY 0x17
|
||||
#define GSM48_MT_CC_MODIFY_COMPL 0x1f
|
||||
#define GSM48_MT_CC_MODIFY_REJECT 0x13
|
||||
#define GSM48_MT_CC_USER_INFO 0x10
|
||||
#define GSM48_MT_CC_HOLD 0x18
|
||||
#define GSM48_MT_CC_HOLD_ACK 0x19
|
||||
#define GSM48_MT_CC_HOLD_REJ 0x1a
|
||||
#define GSM48_MT_CC_RETR 0x1c
|
||||
#define GSM48_MT_CC_RETR_ACK 0x1d
|
||||
#define GSM48_MT_CC_RETR_REJ 0x1e
|
||||
|
||||
#define GSM48_MT_CC_DISCONNECT 0x25
|
||||
#define GSM48_MT_CC_RELEASE 0x2d
|
||||
#define GSM48_MT_CC_RELEASE_COMPL 0x2a
|
||||
|
||||
#define GSM48_MT_CC_CONG_CTRL 0x39
|
||||
#define GSM48_MT_CC_NOTIFY 0x3e
|
||||
#define GSM48_MT_CC_STATUS 0x3d
|
||||
#define GSM48_MT_CC_STATUS_ENQ 0x34
|
||||
#define GSM48_MT_CC_START_DTMF 0x35
|
||||
#define GSM48_MT_CC_STOP_DTMF 0x31
|
||||
#define GSM48_MT_CC_STOP_DTMF_ACK 0x32
|
||||
#define GSM48_MT_CC_START_DTMF_ACK 0x36
|
||||
#define GSM48_MT_CC_START_DTMF_REJ 0x37
|
||||
#define GSM48_MT_CC_FACILITY 0x3a
|
||||
|
||||
/* FIXME: Table 10.4 / 10.4a (GPRS) */
|
||||
|
||||
/* Section 10.5.2.26, Table 10.5.64 */
|
||||
#define GSM48_PM_MASK 0x03
|
||||
#define GSM48_PM_NORMAL 0x00
|
||||
#define GSM48_PM_EXTENDED 0x01
|
||||
#define GSM48_PM_REORG 0x02
|
||||
#define GSM48_PM_SAME 0x03
|
||||
|
||||
/* Chapter 10.5.3.5 / Table 10.5.93 */
|
||||
#define GSM48_LUPD_NORMAL 0x0
|
||||
#define GSM48_LUPD_PERIODIC 0x1
|
||||
#define GSM48_LUPD_IMSI_ATT 0x2
|
||||
#define GSM48_LUPD_RESERVED 0x3
|
||||
|
||||
/* Table 10.5.4 */
|
||||
#define GSM_MI_TYPE_MASK 0x07
|
||||
#define GSM_MI_TYPE_NONE 0x00
|
||||
#define GSM_MI_TYPE_IMSI 0x01
|
||||
#define GSM_MI_TYPE_IMEI 0x02
|
||||
#define GSM_MI_TYPE_IMEISV 0x03
|
||||
#define GSM_MI_TYPE_TMSI 0x04
|
||||
#define GSM_MI_ODD 0x08
|
||||
|
||||
#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */
|
||||
#define GSM48_IE_MOBILE_ID 0x17
|
||||
#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */
|
||||
#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */
|
||||
#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */
|
||||
#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */
|
||||
#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */
|
||||
|
||||
#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */
|
||||
#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */
|
||||
#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */
|
||||
#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */
|
||||
#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */
|
||||
#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */
|
||||
#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */
|
||||
#define GSM48_IE_NOTIFY 0x27 /* 10.5.4.20 */
|
||||
#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */
|
||||
#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */
|
||||
#define GSM48_IE_CONN_BCD 0x4c /* 10.5.4.13 */
|
||||
#define GSM48_IE_CONN_SUB 0x4d /* 10.5.4.14 */
|
||||
#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */
|
||||
#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */
|
||||
#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */
|
||||
#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */
|
||||
#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */
|
||||
#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */
|
||||
#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */
|
||||
#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */
|
||||
#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */
|
||||
#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */
|
||||
#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */
|
||||
#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */
|
||||
#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */
|
||||
#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */
|
||||
#define GSM48_IE_REPEAT_CIR 0xd1 /* 10.5.4.22 */
|
||||
#define GSM48_IE_REPEAT_SEQ 0xd3 /* 10.5.4.22 */
|
||||
|
||||
/* Section 10.5.4.11 / Table 10.5.122 */
|
||||
#define GSM48_CAUSE_CS_GSM 0x60
|
||||
|
||||
/* Section 9.1.2 / Table 9.3 */
|
||||
#define GSM48_IE_FRQLIST_AFTER 0x05
|
||||
#define GSM48_IE_CELL_CH_DESC 0x62
|
||||
#define GSM48_IE_MSLOT_DESC 0x10
|
||||
#define GSM48_IE_CHANMODE_1 0x63
|
||||
#define GSM48_IE_CHANMODE_2 0x11
|
||||
#define GSM48_IE_CHANMODE_3 0x13
|
||||
#define GSM48_IE_CHANMODE_4 0x14
|
||||
#define GSM48_IE_CHANMODE_5 0x15
|
||||
#define GSM48_IE_CHANMODE_6 0x16
|
||||
#define GSM48_IE_CHANMODE_7 0x17
|
||||
#define GSM48_IE_CHANMODE_8 0x18
|
||||
#define GSM48_IE_CHANDESC_2 0x64
|
||||
/* FIXME */
|
||||
|
||||
/* Section 10.5.4.23 / Table 10.5.130 */
|
||||
enum gsm48_signal_val {
|
||||
GSM48_SIGNAL_DIALTONE = 0x00,
|
||||
GSM48_SIGNAL_RINGBACK = 0x01,
|
||||
GSM48_SIGNAL_INTERCEPT = 0x02,
|
||||
GSM48_SIGNAL_NET_CONG = 0x03,
|
||||
GSM48_SIGNAL_BUSY = 0x04,
|
||||
GSM48_SIGNAL_CONFIRM = 0x05,
|
||||
GSM48_SIGNAL_ANSWER = 0x06,
|
||||
GSM48_SIGNAL_CALL_WAIT = 0x07,
|
||||
GSM48_SIGNAL_OFF_HOOK = 0x08,
|
||||
GSM48_SIGNAL_OFF = 0x3f,
|
||||
GSM48_SIGNAL_ALERT_OFF = 0x4f,
|
||||
};
|
||||
|
||||
enum gsm48_cause_loc {
|
||||
GSM48_CAUSE_LOC_USER = 0x00,
|
||||
GSM48_CAUSE_LOC_PRN_S_LU = 0x01,
|
||||
GSM48_CAUSE_LOC_PUN_S_LU = 0x02,
|
||||
GSM48_CAUSE_LOC_TRANS_NET = 0x03,
|
||||
GSM48_CAUSE_LOC_PUN_S_RU = 0x04,
|
||||
GSM48_CAUSE_LOC_PRN_S_RU = 0x05,
|
||||
/* not defined */
|
||||
GSM48_CAUSE_LOC_INN_NET = 0x07,
|
||||
GSM48_CAUSE_LOC_NET_BEYOND = 0x0a,
|
||||
};
|
||||
|
||||
/* Section 10.5.2.31 RR Cause / Table 10.5.70 */
|
||||
enum gsm48_rr_cause {
|
||||
GSM48_RR_CAUSE_NORMAL = 0x00,
|
||||
GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01,
|
||||
GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02,
|
||||
GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03,
|
||||
GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04,
|
||||
GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05,
|
||||
GSM48_RR_CAUSE_HNDOVER_IMP = 0x06,
|
||||
GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07,
|
||||
GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08,
|
||||
GSM48_RR_CAUSE_CALL_CLEARED = 0x41,
|
||||
GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f,
|
||||
GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60,
|
||||
GSM48_RR_CAUSE_MSG_TYPE_N = 0x61,
|
||||
GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62,
|
||||
GSM48_RR_CAUSE_COND_IE_ERROR = 0x64,
|
||||
GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65,
|
||||
GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f,
|
||||
};
|
||||
|
||||
/* Section 10.5.4.11 CC Cause / Table 10.5.123 */
|
||||
enum gsm48_cc_cause {
|
||||
GSM48_CC_CAUSE_UNASSIGNED_NR = 1,
|
||||
GSM48_CC_CAUSE_NO_ROUTE = 3,
|
||||
GSM48_CC_CAUSE_CHAN_UNACCEPT = 6,
|
||||
GSM48_CC_CAUSE_OP_DET_BARRING = 8,
|
||||
GSM48_CC_CAUSE_NORM_CALL_CLEAR = 16,
|
||||
GSM48_CC_CAUSE_USER_BUSY = 17,
|
||||
GSM48_CC_CAUSE_USER_NOTRESPOND = 18,
|
||||
GSM48_CC_CAUSE_USER_ALERTING_NA = 19,
|
||||
GSM48_CC_CAUSE_CALL_REJECTED = 21,
|
||||
GSM48_CC_CAUSE_NUMBER_CHANGED = 22,
|
||||
GSM48_CC_CAUSE_PRE_EMPTION = 25,
|
||||
GSM48_CC_CAUSE_NONSE_USER_CLR = 26,
|
||||
GSM48_CC_CAUSE_DEST_OOO = 27,
|
||||
GSM48_CC_CAUSE_INV_NR_FORMAT = 28,
|
||||
GSM48_CC_CAUSE_FACILITY_REJ = 29,
|
||||
GSM48_CC_CAUSE_RESP_STATUS_INQ = 30,
|
||||
GSM48_CC_CAUSE_NORMAL_UNSPEC = 31,
|
||||
GSM48_CC_CAUSE_NO_CIRCUIT_CHAN = 34,
|
||||
GSM48_CC_CAUSE_NETWORK_OOO = 38,
|
||||
GSM48_CC_CAUSE_TEMP_FAILURE = 41,
|
||||
GSM48_CC_CAUSE_SWITCH_CONG = 42,
|
||||
GSM48_CC_CAUSE_ACC_INF_DISCARD = 43,
|
||||
GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL = 44,
|
||||
GSM48_CC_CAUSE_RESOURCE_UNAVAIL = 47,
|
||||
GSM48_CC_CAUSE_QOS_UNAVAIL = 49,
|
||||
GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC= 50,
|
||||
GSM48_CC_CAUSE_INC_BARRED_CUG = 55,
|
||||
GSM48_CC_CAUSE_BEARER_CAP_UNAUTH= 57,
|
||||
GSM48_CC_CAUSE_BEARER_CA_UNAVAIL= 58,
|
||||
GSM48_CC_CAUSE_SERV_OPT_UNAVAIL = 63,
|
||||
GSM48_CC_CAUSE_BEARERSERV_UNIMPL= 65,
|
||||
GSM48_CC_CAUSE_ACM_GE_ACM_MAX = 68,
|
||||
GSM48_CC_CAUSE_REQ_FAC_NOTIMPL = 69,
|
||||
GSM48_CC_CAUSE_RESTR_BCAP_AVAIL = 70,
|
||||
GSM48_CC_CAUSE_SERV_OPT_UNIMPL = 79,
|
||||
GSM48_CC_CAUSE_INVAL_TRANS_ID = 81,
|
||||
GSM48_CC_CAUSE_USER_NOT_IN_CUG = 87,
|
||||
GSM48_CC_CAUSE_INCOMPAT_DEST = 88,
|
||||
GSM48_CC_CAUSE_INVAL_TRANS_NET = 91,
|
||||
GSM48_CC_CAUSE_SEMANTIC_INCORR = 95,
|
||||
GSM48_CC_CAUSE_INVAL_MAND_INF = 96,
|
||||
GSM48_CC_CAUSE_MSGTYPE_NOTEXIST = 97,
|
||||
GSM48_CC_CAUSE_MSGTYPE_INCOMPAT = 98,
|
||||
GSM48_CC_CAUSE_IE_NOTEXIST = 99,
|
||||
GSM48_CC_CAUSE_COND_IE_ERR = 100,
|
||||
GSM48_CC_CAUSE_MSG_INCOMP_STATE = 101,
|
||||
GSM48_CC_CAUSE_RECOVERY_TIMER = 102,
|
||||
GSM48_CC_CAUSE_PROTO_ERR = 111,
|
||||
GSM48_CC_CAUSE_INTERWORKING = 127,
|
||||
};
|
||||
|
||||
/* Annex G, GSM specific cause values for mobility management */
|
||||
enum gsm48_reject_value {
|
||||
GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2,
|
||||
GSM48_REJECT_ILLEGAL_MS = 3,
|
||||
GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4,
|
||||
GSM48_REJECT_IMEI_NOT_ACCEPTED = 5,
|
||||
GSM48_REJECT_ILLEGAL_ME = 6,
|
||||
GSM48_REJECT_PLMN_NOT_ALLOWED = 11,
|
||||
GSM48_REJECT_LOC_NOT_ALLOWED = 12,
|
||||
GSM48_REJECT_ROAMING_NOT_ALLOWED = 13,
|
||||
GSM48_REJECT_NETWORK_FAILURE = 17,
|
||||
GSM48_REJECT_CONGESTION = 22,
|
||||
GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32,
|
||||
GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33,
|
||||
GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34,
|
||||
GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38,
|
||||
GSM48_REJECT_INCORRECT_MESSAGE = 95,
|
||||
GSM48_REJECT_INVALID_MANDANTORY_INF = 96,
|
||||
GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97,
|
||||
GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98,
|
||||
GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99,
|
||||
GSM48_REJECT_CONDTIONAL_IE_ERROR = 100,
|
||||
GSM48_REJECT_MSG_NOT_COMPATIBLE = 101,
|
||||
GSM48_REJECT_PROTOCOL_ERROR = 111,
|
||||
|
||||
/* according to G.6 Additional cause codes for GMM */
|
||||
GSM48_REJECT_GPRS_NOT_ALLOWED = 7,
|
||||
GSM48_REJECT_SERVICES_NOT_ALLOWED = 8,
|
||||
GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9,
|
||||
GSM48_REJECT_IMPLICITLY_DETACHED = 10,
|
||||
GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14,
|
||||
GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16,
|
||||
};
|
||||
|
||||
enum chreq_type {
|
||||
CHREQ_T_EMERG_CALL,
|
||||
CHREQ_T_CALL_REEST_TCH_F,
|
||||
CHREQ_T_CALL_REEST_TCH_H,
|
||||
CHREQ_T_CALL_REEST_TCH_H_DBL,
|
||||
CHREQ_T_SDCCH,
|
||||
CHREQ_T_TCH_F,
|
||||
CHREQ_T_VOICE_CALL_TCH_H,
|
||||
CHREQ_T_DATA_CALL_TCH_H,
|
||||
CHREQ_T_LOCATION_UPD,
|
||||
CHREQ_T_PAG_R_ANY_NECI0,
|
||||
CHREQ_T_PAG_R_ANY_NECI1,
|
||||
CHREQ_T_PAG_R_TCH_F,
|
||||
CHREQ_T_PAG_R_TCH_FH,
|
||||
CHREQ_T_LMU,
|
||||
CHREQ_T_RESERVED_SDCCH,
|
||||
CHREQ_T_RESERVED_IGNORE,
|
||||
};
|
||||
|
||||
/* Chapter 11.3 */
|
||||
#define GSM48_T301 180, 0
|
||||
#define GSM48_T303 30, 0
|
||||
#define GSM48_T305 30, 0
|
||||
#define GSM48_T306 30, 0
|
||||
#define GSM48_T308 10, 0
|
||||
#define GSM48_T310 180, 0
|
||||
#define GSM48_T313 30, 0
|
||||
#define GSM48_T323 30, 0
|
||||
#define GSM48_T331 30, 0
|
||||
#define GSM48_T333 30, 0
|
||||
#define GSM48_T334 25, 0 /* min 15 */
|
||||
#define GSM48_T338 30, 0
|
||||
|
||||
/* Chapter 5.1.2.2 */
|
||||
#define GSM_CSTATE_NULL 0
|
||||
#define GSM_CSTATE_INITIATED 1
|
||||
#define GSM_CSTATE_MO_CALL_PROC 3
|
||||
#define GSM_CSTATE_CALL_DELIVERED 4
|
||||
#define GSM_CSTATE_CALL_PRESENT 6
|
||||
#define GSM_CSTATE_CALL_RECEIVED 7
|
||||
#define GSM_CSTATE_CONNECT_REQUEST 8
|
||||
#define GSM_CSTATE_MO_TERM_CALL_CONF 9
|
||||
#define GSM_CSTATE_ACTIVE 10
|
||||
#define GSM_CSTATE_DISCONNECT_REQ 12
|
||||
#define GSM_CSTATE_DISCONNECT_IND 12
|
||||
#define GSM_CSTATE_RELEASE_REQ 19
|
||||
#define GSM_CSTATE_MO_ORIG_MODIFY 26
|
||||
#define GSM_CSTATE_MO_TERM_MODIFY 27
|
||||
#define GSM_CSTATE_CONNECT_IND 28
|
||||
|
||||
#define SBIT(a) (1 << a)
|
||||
#define ALL_STATES 0xffffffff
|
||||
|
||||
/* Table 10.5.3/3GPP TS 04.08: Location Area Identification information element */
|
||||
#define GSM_LAC_RESERVED_DETACHED 0x0
|
||||
#define GSM_LAC_RESERVED_ALL_BTS 0xfffe
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Information Transfer Capability */
|
||||
enum gsm48_bcap_itcap {
|
||||
GSM48_BCAP_ITCAP_SPEECH = 0,
|
||||
GSM48_BCAP_ITCAP_UNR_DIG_INF = 1,
|
||||
GSM48_BCAP_ITCAP_3k1_AUDIO = 2,
|
||||
GSM48_BCAP_ITCAP_FAX_G3 = 3,
|
||||
GSM48_BCAP_ITCAP_OTHER = 5,
|
||||
GSM48_BCAP_ITCAP_RESERVED = 7,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Transfer Mode */
|
||||
enum gsm48_bcap_tmod {
|
||||
GSM48_BCAP_TMOD_CIRCUIT = 0,
|
||||
GSM48_BCAP_TMOD_PACKET = 1,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Coding Standard */
|
||||
enum gsm48_bcap_coding {
|
||||
GSM48_BCAP_CODING_GSM_STD = 0,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Radio Channel Requirements */
|
||||
enum gsm48_bcap_rrq {
|
||||
GSM48_BCAP_RRQ_FR_ONLY = 1,
|
||||
GSM48_BCAP_RRQ_DUAL_HR = 2,
|
||||
GSM48_BCAP_RRQ_DUAL_FR = 3,
|
||||
};
|
||||
|
||||
|
||||
#define GSM48_TMSI_LEN 5
|
||||
#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2)
|
||||
#define GSM48_MI_SIZE 32
|
||||
|
||||
|
||||
#endif /* PROTO_GSM_04_08_H */
|
|
@ -0,0 +1,188 @@
|
|||
#ifndef PROTO_GSM_04_11_H
|
||||
#define PROTO_GSM_04_11_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* GSM TS 04.11 definitions */
|
||||
|
||||
/* Chapter 5.2.3: SMC-CS states at the network side */
|
||||
enum gsm411_cp_state {
|
||||
GSM411_CPS_IDLE = 0,
|
||||
GSM411_CPS_MM_CONN_PENDING = 1, /* only MT ! */
|
||||
GSM411_CPS_WAIT_CP_ACK = 2,
|
||||
GSM411_CPS_MM_ESTABLISHED = 3,
|
||||
};
|
||||
|
||||
/* Chapter 6.2.2: SMR states at the network side */
|
||||
enum gsm411_rp_state {
|
||||
GSM411_RPS_IDLE = 0,
|
||||
GSM411_RPS_WAIT_FOR_RP_ACK = 1,
|
||||
GSM411_RPS_WAIT_TO_TX_RP_ACK = 3,
|
||||
};
|
||||
|
||||
/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */
|
||||
#define GSM411_PDISC_SMS 0x09
|
||||
|
||||
/* Chapter 8.1.3 */
|
||||
#define GSM411_MT_CP_DATA 0x01
|
||||
#define GSM411_MT_CP_ACK 0x04
|
||||
#define GSM411_MT_CP_ERROR 0x10
|
||||
|
||||
enum gsm411_cp_ie {
|
||||
GSM411_CP_IE_USER_DATA = 0x01, /* 8.1.4.1 */
|
||||
GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */
|
||||
};
|
||||
|
||||
/* Section 8.1.4.2 / Table 8.2 */
|
||||
enum gsm411_cp_cause {
|
||||
GSM411_CP_CAUSE_NET_FAIL = 17,
|
||||
GSM411_CP_CAUSE_CONGESTION = 22,
|
||||
GSM411_CP_CAUSE_INV_TRANS_ID = 81,
|
||||
GSM411_CP_CAUSE_SEMANT_INC_MSG = 95,
|
||||
GSM411_CP_CAUSE_INV_MAND_INF = 96,
|
||||
GSM411_CP_CAUSE_MSGTYPE_NOTEXIST= 97,
|
||||
GSM411_CP_CAUSE_MSG_INCOMP_STATE= 98,
|
||||
GSM411_CP_CAUSE_IE_NOTEXIST = 99,
|
||||
GSM411_CP_CAUSE_PROTOCOL_ERR = 111,
|
||||
};
|
||||
|
||||
/* Chapter 8.2.2 */
|
||||
#define GSM411_MT_RP_DATA_MO 0x00
|
||||
#define GSM411_MT_RP_DATA_MT 0x01
|
||||
#define GSM411_MT_RP_ACK_MO 0x02
|
||||
#define GSM411_MT_RP_ACK_MT 0x03
|
||||
#define GSM411_MT_RP_ERROR_MO 0x04
|
||||
#define GSM411_MT_RP_ERROR_MT 0x05
|
||||
#define GSM411_MT_RP_SMMA_MO 0x06
|
||||
|
||||
enum gsm411_rp_ie {
|
||||
GSM411_IE_RP_USER_DATA = 0x41, /* 8.2.5.3 */
|
||||
GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */
|
||||
};
|
||||
|
||||
/* Chapter 8.2.5.4 Table 8.4 */
|
||||
enum gsm411_rp_cause {
|
||||
/* valid only for MO */
|
||||
GSM411_RP_CAUSE_MO_NUM_UNASSIGNED = 1,
|
||||
GSM411_RP_CAUSE_MO_OP_DET_BARR = 8,
|
||||
GSM411_RP_CAUSE_MO_CALL_BARRED = 10,
|
||||
GSM411_RP_CAUSE_MO_SMS_REJECTED = 21,
|
||||
GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER = 27,
|
||||
GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR = 28,
|
||||
GSM411_RP_CAUSE_MO_FACILITY_REJ = 29,
|
||||
GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR = 30,
|
||||
GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER = 38,
|
||||
GSM411_RP_CAUSE_MO_TEMP_FAIL = 41,
|
||||
GSM411_RP_CAUSE_MO_CONGESTION = 42,
|
||||
GSM411_RP_CAUSE_MO_RES_UNAVAIL = 47,
|
||||
GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR = 50,
|
||||
GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL = 69,
|
||||
GSM411_RP_CAUSE_MO_INTERWORKING = 127,
|
||||
/* valid only for MT */
|
||||
GSM411_RP_CAUSE_MT_MEM_EXCEEDED = 22,
|
||||
/* valid for both directions */
|
||||
GSM411_RP_CAUSE_INV_TRANS_REF = 81,
|
||||
GSM411_RP_CAUSE_SEMANT_INC_MSG = 95,
|
||||
GSM411_RP_CAUSE_INV_MAND_INF = 96,
|
||||
GSM411_RP_CAUSE_MSGTYPE_NOTEXIST = 97,
|
||||
GSM411_RP_CAUSE_MSG_INCOMP_STATE = 98,
|
||||
GSM411_RP_CAUSE_IE_NOTEXIST = 99,
|
||||
GSM411_RP_CAUSE_PROTOCOL_ERR = 111,
|
||||
};
|
||||
|
||||
/* Chapter 10: Timers */
|
||||
#define GSM411_TMR_TR1M 40, 0 /* 35 < x < 45 seconds */
|
||||
#define GSM411_TMR_TRAM 30, 0 /* 25 < x < 35 seconds */
|
||||
#define GSM411_TMR_TR2M 15, 0 /* 12 < x < 20 seconds */
|
||||
|
||||
#define GSM411_TMR_TC1A 30, 0
|
||||
|
||||
/* Chapter 8.2.1 */
|
||||
struct gsm411_rp_hdr {
|
||||
uint8_t len;
|
||||
uint8_t msg_type;
|
||||
uint8_t msg_ref;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* our own enum, not related to on-air protocol */
|
||||
enum sms_alphabet {
|
||||
DCS_NONE,
|
||||
DCS_7BIT_DEFAULT,
|
||||
DCS_UCS2,
|
||||
DCS_8BIT_DATA,
|
||||
};
|
||||
|
||||
/* GSM 03.40 / Chapter 9.2.3.1: TP-Message-Type-Indicator */
|
||||
#define GSM340_SMS_DELIVER_SC2MS 0x00
|
||||
#define GSM340_SMS_DELIVER_REP_MS2SC 0x00
|
||||
#define GSM340_SMS_STATUS_REP_SC2MS 0x02
|
||||
#define GSM340_SMS_COMMAND_MS2SC 0x02
|
||||
#define GSM340_SMS_SUBMIT_MS2SC 0x01
|
||||
#define GSM340_SMS_SUBMIT_REP_SC2MS 0x01
|
||||
#define GSM340_SMS_RESSERVED 0x03
|
||||
|
||||
/* GSM 03.40 / Chapter 9.2.3.2: TP-More-Messages-to-Send */
|
||||
#define GSM340_TP_MMS_MORE 0
|
||||
#define GSM340_TP_MMS_NO_MORE 1
|
||||
|
||||
/* GSM 03.40 / Chapter 9.2.3.3: TP-Validity-Period-Format */
|
||||
#define GSM340_TP_VPF_NONE 0
|
||||
#define GSM340_TP_VPF_RELATIVE 2
|
||||
#define GSM340_TP_VPF_ENHANCED 1
|
||||
#define GSM340_TP_VPF_ABSOLUTE 3
|
||||
|
||||
/* GSM 03.40 / Chapter 9.2.3.4: TP-Status-Report-Indication */
|
||||
#define GSM340_TP_SRI_NONE 0
|
||||
#define GSM340_TP_SRI_PRESENT 1
|
||||
|
||||
/* GSM 03.40 / Chapter 9.2.3.5: TP-Status-Report-Request */
|
||||
#define GSM340_TP_SRR_NONE 0
|
||||
#define GSM340_TP_SRR_REQUESTED 1
|
||||
|
||||
/* GSM 03.40 / Chapter 9.2.3.9: TP-Protocol-Identifier */
|
||||
/* telematic interworking (001 or 111 in bits 7-5) */
|
||||
#define GSM340_TP_PID_IMPLICIT 0x00
|
||||
#define GSM340_TP_PID_TELEX 0x01
|
||||
#define GSM340_TP_PID_FAX_G3 0x02
|
||||
#define GSM340_TP_PID_FAX_G4 0x03
|
||||
#define GSM340_TP_PID_VOICE 0x04
|
||||
#define GSM430_TP_PID_ERMES 0x05
|
||||
#define GSM430_TP_PID_NATIONAL_PAGING 0x06
|
||||
#define GSM430_TP_PID_VIDEOTEX 0x07
|
||||
#define GSM430_TP_PID_TELETEX_UNSPEC 0x08
|
||||
#define GSM430_TP_PID_TELETEX_PSPDN 0x09
|
||||
#define GSM430_TP_PID_TELETEX_CSPDN 0x0a
|
||||
#define GSM430_TP_PID_TELETEX_PSTN 0x0b
|
||||
#define GSM430_TP_PID_TELETEX_ISDN 0x0c
|
||||
#define GSM430_TP_PID_TELETEX_UCI 0x0d
|
||||
#define GSM430_TP_PID_MSG_HANDLING 0x10
|
||||
#define GSM430_TP_PID_MSG_X400 0x11
|
||||
#define GSM430_TP_PID_EMAIL 0x12
|
||||
#define GSM430_TP_PID_GSM_MS 0x1f
|
||||
/* if bit 7 = 0 and bit 6 = 1 */
|
||||
#define GSM430_TP_PID_SMS_TYPE_0 0
|
||||
#define GSM430_TP_PID_SMS_TYPE_1 1
|
||||
#define GSM430_TP_PID_SMS_TYPE_2 2
|
||||
#define GSM430_TP_PID_SMS_TYPE_3 3
|
||||
#define GSM430_TP_PID_SMS_TYPE_4 4
|
||||
#define GSM430_TP_PID_SMS_TYPE_5 5
|
||||
#define GSM430_TP_PID_SMS_TYPE_6 6
|
||||
#define GSM430_TP_PID_SMS_TYPE_7 7
|
||||
#define GSM430_TP_PID_RETURN_CALL_MSG 0x1f
|
||||
#define GSM430_TP_PID_ME_DATA_DNLOAD 0x3d
|
||||
#define GSM430_TP_PID_ME_DE_PERSONAL 0x3e
|
||||
#define GSM430_TP_PID_ME_SIM_DNLOAD 0x3f
|
||||
|
||||
/* GSM 03.38 Chapter 4: SMS Data Coding Scheme */
|
||||
#define GSM338_DCS_00_
|
||||
|
||||
#define GSM338_DCS_1110_7BIT (0 << 2)
|
||||
#define GSM338_DCS_1111_7BIT (0 << 2)
|
||||
#define GSM338_DCS_1111_8BIT_DATA (1 << 2)
|
||||
#define GSM338_DCS_1111_CLASS0 0
|
||||
#define GSM338_DCS_1111_CLASS1_ME 1
|
||||
#define GSM338_DCS_1111_CLASS2_SIM 2
|
||||
#define GSM338_DCS_1111_CLASS3_TE 3 /* See TS 07.05 */
|
||||
|
||||
#endif /* PROTO_GSM_04_11_H */
|
|
@ -0,0 +1,126 @@
|
|||
#ifndef PROTO_GSM_04_80_H
|
||||
#define PROTO_GSM_04_80_H
|
||||
|
||||
/* GSM TS 04.80 definitions (Supplementary Services Specification, Formats and Coding) */
|
||||
|
||||
/* Section 3.4 */
|
||||
#define GSM0480_MTYPE_RELEASE_COMPLETE 0x2A
|
||||
#define GSM0480_MTYPE_FACILITY 0x3A
|
||||
#define GSM0480_MTYPE_REGISTER 0x3B
|
||||
|
||||
/* Section 3.5 */
|
||||
#define GSM0480_IE_FACILITY 0x1C
|
||||
#define GSM0480_IE_SS_VERSION 0x7F
|
||||
|
||||
/* Section 3.6.2 */
|
||||
#define GSM0480_CTYPE_INVOKE 0xA1
|
||||
#define GSM0480_CTYPE_RETURN_RESULT 0xA2
|
||||
#define GSM0480_CTYPE_RETURN_ERROR 0xA3
|
||||
#define GSM0480_CTYPE_REJECT 0xA4
|
||||
|
||||
/* Section 3.6.3 */
|
||||
#define GSM0480_COMPIDTAG_INVOKE_ID 0x02
|
||||
#define GSM0480_COMPIDTAG_LINKED_ID 0x80
|
||||
|
||||
/* Section 3.6.4 */
|
||||
#define GSM0480_OPERATION_CODE 0x02
|
||||
|
||||
/* Section 3.6.5 */
|
||||
#define GSM_0480_SEQUENCE_TAG 0x30
|
||||
#define GSM_0480_SET_TAG 0x31
|
||||
|
||||
/* Section 3.6.6 */
|
||||
#define GSM_0480_ERROR_CODE_TAG 0x02
|
||||
|
||||
/* Section 3.6.7 */
|
||||
/* Table 3.13 */
|
||||
#define GSM_0480_PROBLEM_CODE_TAG_GENERAL 0x80
|
||||
#define GSM_0480_PROBLEM_CODE_TAG_INVOKE 0x81
|
||||
#define GSM_0480_PROBLEM_CODE_TAG_RETURN_RESULT 0x82
|
||||
#define GSM_0480_PROBLEM_CODE_TAG_RETURN_ERROR 0x83
|
||||
|
||||
/* Table 3.14 */
|
||||
#define GSM_0480_GEN_PROB_CODE_UNRECOGNISED 0x00
|
||||
#define GSM_0480_GEN_PROB_CODE_MISTYPED 0x01
|
||||
#define GSM_0480_GEN_PROB_CODE_BAD_STRUCTURE 0x02
|
||||
|
||||
/* Table 3.15 */
|
||||
#define GSM_0480_INVOKE_PROB_CODE_DUPLICATE_INVOKE_ID 0x00
|
||||
#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION 0x01
|
||||
#define GSM_0480_INVOKE_PROB_CODE_MISTYPED_PARAMETER 0x02
|
||||
#define GSM_0480_INVOKE_PROB_CODE_RESOURCE_LIMITATION 0x03
|
||||
#define GSM_0480_INVOKE_PROB_CODE_INITIATING_RELEASE 0x04
|
||||
#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_LINKED_ID 0x05
|
||||
#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_RESPONSE 0x06
|
||||
#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_OPERATION 0x07
|
||||
|
||||
/* Table 3.16 */
|
||||
#define GSM_0480_RESULT_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00
|
||||
#define GSM_0480_RESULT_PROB_CODE_RETURN_RESULT_UNEXPECTED 0x01
|
||||
#define GSM_0480_RESULT_PROB_CODE_MISTYPED_PARAMETER 0x02
|
||||
|
||||
/* Table 3.17 */
|
||||
#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00
|
||||
#define GSM_0480_ERROR_PROB_CODE_RETURN_ERROR_UNEXPECTED 0x01
|
||||
#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_ERROR 0x02
|
||||
#define GSM_0480_ERROR_PROB_CODE_UNEXPECTED_ERROR 0x03
|
||||
#define GSM_0480_ERROR_PROB_CODE_MISTYPED_PARAMETER 0x04
|
||||
|
||||
/* Section 4.5 */
|
||||
#define GSM0480_OP_CODE_REGISTER_SS 0x0A
|
||||
#define GSM0480_OP_CODE_ERASE_SS 0x0B
|
||||
#define GSM0480_OP_CODE_ACTIVATE_SS 0x0C
|
||||
#define GSM0480_OP_CODE_DEACTIVATE_SS 0x0D
|
||||
#define GSM0480_OP_CODE_INTERROGATE_SS 0x0E
|
||||
#define GSM0480_OP_CODE_NOTIFY_SS 0x10
|
||||
#define GSM0480_OP_CODE_REGISTER_PASSWORD 0x11
|
||||
#define GSM0480_OP_CODE_GET_PASSWORD 0x12
|
||||
#define GSM0480_OP_CODE_PROCESS_USS_DATA 0x13
|
||||
#define GSM0480_OP_CODE_FORWARD_CHECK_SS_IND 0x26
|
||||
#define GSM0480_OP_CODE_PROCESS_USS_REQ 0x3B
|
||||
#define GSM0480_OP_CODE_USS_REQUEST 0x3C
|
||||
#define GSM0480_OP_CODE_USS_NOTIFY 0x3D
|
||||
#define GSM0480_OP_CODE_FORWARD_CUG_INFO 0x78
|
||||
#define GSM0480_OP_CODE_SPLIT_MPTY 0x79
|
||||
#define GSM0480_OP_CODE_RETRIEVE_MPTY 0x7A
|
||||
#define GSM0480_OP_CODE_HOLD_MPTY 0x7B
|
||||
#define GSM0480_OP_CODE_BUILD_MPTY 0x7C
|
||||
#define GSM0480_OP_CODE_FORWARD_CHARGE_ADVICE 0x7D
|
||||
|
||||
#define GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER 0x01
|
||||
#define GSM0480_ERR_CODE_ILLEGAL_SUBSCRIBER 0x09
|
||||
#define GSM0480_ERR_CODE_BEARER_SERVICE_NOT_PROVISIONED 0x0A
|
||||
#define GSM0480_ERR_CODE_TELESERVICE_NOT_PROVISIONED 0x0B
|
||||
#define GSM0480_ERR_CODE_ILLEGAL_EQUIPMENT 0x0C
|
||||
#define GSM0480_ERR_CODE_CALL_BARRED 0x0D
|
||||
#define GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION 0x10
|
||||
#define GSM0480_ERR_CODE_SS_ERROR_STATUS 0x11
|
||||
#define GSM0480_ERR_CODE_SS_NOT_AVAILABLE 0x12
|
||||
#define GSM0480_ERR_CODE_SS_SUBSCRIPTION_VIOLATION 0x13
|
||||
#define GSM0480_ERR_CODE_SS_INCOMPATIBILITY 0x14
|
||||
#define GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED 0x15
|
||||
#define GSM0480_ERR_CODE_ABSENT_SUBSCRIBER 0x1B
|
||||
#define GSM0480_ERR_CODE_SYSTEM_FAILURE 0x22
|
||||
#define GSM0480_ERR_CODE_DATA_MISSING 0x23
|
||||
#define GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE 0x24
|
||||
#define GSM0480_ERR_CODE_PW_REGISTRATION_FAILURE 0x25
|
||||
#define GSM0480_ERR_CODE_NEGATIVE_PW_CHECK 0x26
|
||||
#define GSM0480_ERR_CODE_NUM_PW_ATTEMPTS_VIOLATION 0x2B
|
||||
#define GSM0480_ERR_CODE_UNKNOWN_ALPHABET 0x47
|
||||
#define GSM0480_ERR_CODE_USSD_BUSY 0x48
|
||||
#define GSM0480_ERR_CODE_MAX_MPTY_PARTICIPANTS 0x7E
|
||||
#define GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE 0x7F
|
||||
|
||||
/* ASN.1 type-tags */
|
||||
#define ASN1_BOOLEAN_TAG 0x01
|
||||
#define ASN1_INTEGER_TAG 0x02
|
||||
#define ASN1_BIT_STRING_TAG 0x03
|
||||
#define ASN1_OCTET_STRING_TAG 0x04
|
||||
#define ASN1_NULL_TYPE_TAG 0x05
|
||||
#define ASN1_OBJECT_ID_TAG 0x06
|
||||
#define ASN1_UTF8_STRING_TAG 0x0C
|
||||
#define ASN1_PRINTABLE_STRING_TAG 0x13
|
||||
#define ASN1_IA5_STRING_TAG 0x16
|
||||
#define ASN1_UNICODE_STRING_TAG 0x1E
|
||||
|
||||
#endif /* PROTO_GSM_04_80_H */
|
|
@ -0,0 +1,512 @@
|
|||
#ifndef PROTO_GSM_08_58_H
|
||||
#define PROTO_GSM_08_58_H
|
||||
|
||||
/* GSM Radio Signalling Link messages on the A-bis interface
|
||||
* 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
|
||||
|
||||
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct abis_rsl_common_hdr {
|
||||
uint8_t msg_discr;
|
||||
uint8_t msg_type;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chapter 8.3 */
|
||||
struct abis_rsl_rll_hdr {
|
||||
struct abis_rsl_common_hdr c;
|
||||
uint8_t ie_chan;
|
||||
uint8_t chan_nr;
|
||||
uint8_t ie_link_id;
|
||||
uint8_t link_id;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chapter 8.3 and 8.4 */
|
||||
struct abis_rsl_dchan_hdr {
|
||||
struct abis_rsl_common_hdr c;
|
||||
uint8_t ie_chan;
|
||||
uint8_t chan_nr;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Chapter 9.1 */
|
||||
#define ABIS_RSL_MDISC_RLL 0x02
|
||||
#define ABIS_RSL_MDISC_DED_CHAN 0x08
|
||||
#define ABIS_RSL_MDISC_COM_CHAN 0x0c
|
||||
#define ABIS_RSL_MDISC_TRX 0x10
|
||||
#define ABIS_RSL_MDISC_LOC 0x20
|
||||
#define ABIS_RSL_MDISC_IPACCESS 0x7e
|
||||
#define ABIS_RSL_MDISC_TRANSP 0x01
|
||||
|
||||
#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01)
|
||||
|
||||
/* Chapter 9.1 */
|
||||
enum abis_rsl_msgtype {
|
||||
/* Radio Link Layer Management */
|
||||
RSL_MT_DATA_REQ = 0x01,
|
||||
RSL_MT_DATA_IND,
|
||||
RSL_MT_ERROR_IND,
|
||||
RSL_MT_EST_REQ,
|
||||
RSL_MT_EST_CONF,
|
||||
RSL_MT_EST_IND,
|
||||
RSL_MT_REL_REQ,
|
||||
RSL_MT_REL_CONF,
|
||||
RSL_MT_REL_IND,
|
||||
RSL_MT_UNIT_DATA_REQ,
|
||||
RSL_MT_UNIT_DATA_IND, /* 0x0b */
|
||||
|
||||
/* Common Channel Management / TRX Management */
|
||||
RSL_MT_BCCH_INFO = 0x11,
|
||||
RSL_MT_CCCH_LOAD_IND,
|
||||
RSL_MT_CHAN_RQD,
|
||||
RSL_MT_DELETE_IND,
|
||||
RSL_MT_PAGING_CMD,
|
||||
RSL_MT_IMMEDIATE_ASSIGN_CMD,
|
||||
RSL_MT_SMS_BC_REQ,
|
||||
/* empty */
|
||||
RSL_MT_RF_RES_IND = 0x19,
|
||||
RSL_MT_SACCH_FILL,
|
||||
RSL_MT_OVERLOAD,
|
||||
RSL_MT_ERROR_REPORT,
|
||||
RSL_MT_SMS_BC_CMD,
|
||||
RSL_MT_CBCH_LOAD_IND,
|
||||
RSL_MT_NOT_CMD, /* 0x1f */
|
||||
|
||||
/* Dedicate Channel Management */
|
||||
RSL_MT_CHAN_ACTIV = 0x21,
|
||||
RSL_MT_CHAN_ACTIV_ACK,
|
||||
RSL_MT_CHAN_ACTIV_NACK,
|
||||
RSL_MT_CONN_FAIL,
|
||||
RSL_MT_DEACTIVATE_SACCH,
|
||||
RSL_MT_ENCR_CMD,
|
||||
RSL_MT_HANDO_DET,
|
||||
RSL_MT_MEAS_RES,
|
||||
RSL_MT_MODE_MODIFY_REQ,
|
||||
RSL_MT_MODE_MODIFY_ACK,
|
||||
RSL_MT_MODE_MODIFY_NACK,
|
||||
RSL_MT_PHY_CONTEXT_REQ,
|
||||
RSL_MT_PHY_CONTEXT_CONF,
|
||||
RSL_MT_RF_CHAN_REL,
|
||||
RSL_MT_MS_POWER_CONTROL,
|
||||
RSL_MT_BS_POWER_CONTROL, /* 0x30 */
|
||||
RSL_MT_PREPROC_CONFIG,
|
||||
RSL_MT_PREPROC_MEAS_RES,
|
||||
RSL_MT_RF_CHAN_REL_ACK,
|
||||
RSL_MT_SACCH_INFO_MODIFY,
|
||||
RSL_MT_TALKER_DET,
|
||||
RSL_MT_LISTENER_DET,
|
||||
RSL_MT_REMOTE_CODEC_CONF_REP,
|
||||
RSL_MT_RTD_REP,
|
||||
RSL_MT_PRE_HANDO_NOTIF,
|
||||
RSL_MT_MR_CODEC_MOD_REQ,
|
||||
RSL_MT_MR_CODEC_MOD_ACK,
|
||||
RSL_MT_MR_CODEC_MOD_NACK,
|
||||
RSL_MT_MR_CODEC_MOD_PER,
|
||||
RSL_MT_TFO_REP,
|
||||
RSL_MT_TFO_MOD_REQ, /* 0x3f */
|
||||
RSL_MT_LOCATION_INFO = 0x41,
|
||||
|
||||
/* ip.access specific RSL message types */
|
||||
RSL_MT_IPAC_DIR_RETR_ENQ = 0x40,
|
||||
RSL_MT_IPAC_PDCH_ACT = 0x48,
|
||||
RSL_MT_IPAC_PDCH_ACT_ACK,
|
||||
RSL_MT_IPAC_PDCH_ACT_NACK,
|
||||
RSL_MT_IPAC_PDCH_DEACT = 0x4b,
|
||||
RSL_MT_IPAC_PDCH_DEACT_ACK,
|
||||
RSL_MT_IPAC_PDCH_DEACT_NACK,
|
||||
RSL_MT_IPAC_CONNECT_MUX = 0x50,
|
||||
RSL_MT_IPAC_CONNECT_MUX_ACK,
|
||||
RSL_MT_IPAC_CONNECT_MUX_NACK,
|
||||
RSL_MT_IPAC_BIND_MUX = 0x53,
|
||||
RSL_MT_IPAC_BIND_MUX_ACK,
|
||||
RSL_MT_IPAC_BIND_MUX_NACK,
|
||||
RSL_MT_IPAC_DISC_MUX = 0x56,
|
||||
RSL_MT_IPAC_DISC_MUX_ACK,
|
||||
RSL_MT_IPAC_DISC_MUX_NACK,
|
||||
RSL_MT_IPAC_CRCX = 0x70, /* Bind to local BTS RTP port */
|
||||
RSL_MT_IPAC_CRCX_ACK,
|
||||
RSL_MT_IPAC_CRCX_NACK,
|
||||
RSL_MT_IPAC_MDCX = 0x73,
|
||||
RSL_MT_IPAC_MDCX_ACK,
|
||||
RSL_MT_IPAC_MDCX_NACK,
|
||||
RSL_MT_IPAC_DLCX_IND = 0x76,
|
||||
RSL_MT_IPAC_DLCX = 0x77,
|
||||
RSL_MT_IPAC_DLCX_ACK,
|
||||
RSL_MT_IPAC_DLCX_NACK,
|
||||
};
|
||||
|
||||
/* Siemens vendor-specific */
|
||||
enum abis_rsl_msgtype_siemens {
|
||||
RSL_MT_SIEMENS_MRPCI = 0x41,
|
||||
RSL_MT_SIEMENS_INTRAC_HO_COND_IND = 0x42,
|
||||
RSL_MT_SIEMENS_INTERC_HO_COND_IND = 0x43,
|
||||
RSL_MT_SIEMENS_FORCED_HO_REQ = 0x44,
|
||||
RSL_MT_SIEMENS_PREF_AREA_REQ = 0x45,
|
||||
RSL_MT_SIEMENS_PREF_AREA = 0x46,
|
||||
RSL_MT_SIEMENS_START_TRACE = 0x47,
|
||||
RSL_MT_SIEMENS_START_TRACE_ACK = 0x48,
|
||||
RSL_MT_SIEMENS_STOP_TRACE = 0x49,
|
||||
RSL_MT_SIEMENS_TRMR = 0x4a,
|
||||
RSL_MT_SIEMENS_HO_FAIL_IND = 0x4b,
|
||||
RSL_MT_SIEMENS_STOP_TRACE_ACK = 0x4c,
|
||||
RSL_MT_SIEMENS_UPLF = 0x4d,
|
||||
RSL_MT_SIEMENS_UPLB = 0x4e,
|
||||
RSL_MT_SIEMENS_SET_SYS_INFO_10 = 0x4f,
|
||||
RSL_MT_SIEMENS_MODIF_COND_IND = 0x50,
|
||||
};
|
||||
|
||||
/* Chapter 9.3 */
|
||||
enum abis_rsl_ie {
|
||||
RSL_IE_CHAN_NR = 0x01,
|
||||
RSL_IE_LINK_IDENT,
|
||||
RSL_IE_ACT_TYPE,
|
||||
RSL_IE_BS_POWER,
|
||||
RSL_IE_CHAN_IDENT,
|
||||
RSL_IE_CHAN_MODE,
|
||||
RSL_IE_ENCR_INFO,
|
||||
RSL_IE_FRAME_NUMBER,
|
||||
RSL_IE_HANDO_REF,
|
||||
RSL_IE_L1_INFO,
|
||||
RSL_IE_L3_INFO,
|
||||
RSL_IE_MS_IDENTITY,
|
||||
RSL_IE_MS_POWER,
|
||||
RSL_IE_PAGING_GROUP,
|
||||
RSL_IE_PAGING_LOAD,
|
||||
RSL_IE_PYHS_CONTEXT = 0x10,
|
||||
RSL_IE_ACCESS_DELAY,
|
||||
RSL_IE_RACH_LOAD,
|
||||
RSL_IE_REQ_REFERENCE,
|
||||
RSL_IE_RELEASE_MODE,
|
||||
RSL_IE_RESOURCE_INFO,
|
||||
RSL_IE_RLM_CAUSE,
|
||||
RSL_IE_STARTNG_TIME,
|
||||
RSL_IE_TIMING_ADVANCE,
|
||||
RSL_IE_UPLINK_MEAS,
|
||||
RSL_IE_CAUSE,
|
||||
RSL_IE_MEAS_RES_NR,
|
||||
RSL_IE_MSG_ID,
|
||||
/* reserved */
|
||||
RSL_IE_SYSINFO_TYPE = 0x1e,
|
||||
RSL_IE_MS_POWER_PARAM,
|
||||
RSL_IE_BS_POWER_PARAM,
|
||||
RSL_IE_PREPROC_PARAM,
|
||||
RSL_IE_PREPROC_MEAS,
|
||||
RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */
|
||||
RSL_IE_SMSCB_INFO = 0x24,
|
||||
RSL_IE_MS_TIMING_OFFSET,
|
||||
RSL_IE_ERR_MSG,
|
||||
RSL_IE_FULL_BCCH_INFO,
|
||||
RSL_IE_CHAN_NEEDED,
|
||||
RSL_IE_CB_CMD_TYPE,
|
||||
RSL_IE_SMSCB_MSG,
|
||||
RSL_IE_FULL_IMM_ASS_INFO,
|
||||
RSL_IE_SACCH_INFO,
|
||||
RSL_IE_CBCH_LOAD_INFO,
|
||||
RSL_IE_SMSCB_CHAN_INDICATOR,
|
||||
RSL_IE_GROUP_CALL_REF,
|
||||
RSL_IE_CHAN_DESC = 0x30,
|
||||
RSL_IE_NCH_DRX_INFO,
|
||||
RSL_IE_CMD_INDICATOR,
|
||||
RSL_IE_EMLPP_PRIO,
|
||||
RSL_IE_UIC,
|
||||
RSL_IE_MAIN_CHAN_REF,
|
||||
RSL_IE_MR_CONFIG,
|
||||
RSL_IE_MR_CONTROL,
|
||||
RSL_IE_SUP_CODEC_TYPES,
|
||||
RSL_IE_CODEC_CONFIG,
|
||||
RSL_IE_RTD,
|
||||
RSL_IE_TFO_STATUS,
|
||||
RSL_IE_LLP_APDU,
|
||||
/* Siemens vendor-specific */
|
||||
RSL_IE_SIEMENS_MRPCI = 0x40,
|
||||
RSL_IE_SIEMENS_PREF_AREA_TYPE = 0x43,
|
||||
RSL_IE_SIEMENS_ININ_CELL_HO_PAR = 0x45,
|
||||
RSL_IE_SIEMENS_TRACE_REF_NR = 0x46,
|
||||
RSL_IE_SIEMENS_INT_TRACE_IDX = 0x47,
|
||||
RSL_IE_SIEMENS_L2_HDR_INFO = 0x48,
|
||||
RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e,
|
||||
RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f,
|
||||
|
||||
/* ip.access */
|
||||
RSL_IE_IPAC_SRTP_CONFIG = 0xe0,
|
||||
RSL_IE_IPAC_PROXY_UDP = 0xe1,
|
||||
RSL_IE_IPAC_BSCMPL_TOUT = 0xe2,
|
||||
RSL_IE_IPAC_REMOTE_IP = 0xf0,
|
||||
RSL_IE_IPAC_REMOTE_PORT = 0xf1,
|
||||
RSL_IE_IPAC_RTP_PAYLOAD = 0xf2,
|
||||
RSL_IE_IPAC_LOCAL_PORT = 0xf3,
|
||||
RSL_IE_IPAC_SPEECH_MODE = 0xf4,
|
||||
RSL_IE_IPAC_LOCAL_IP = 0xf5,
|
||||
RSL_IE_IPAC_CONN_STAT = 0xf6,
|
||||
RSL_IE_IPAC_HO_C_PARMS = 0xf7,
|
||||
RSL_IE_IPAC_CONN_ID = 0xf8,
|
||||
RSL_IE_IPAC_RTP_CSD_FMT = 0xf9,
|
||||
RSL_IE_IPAC_RTP_JIT_BUF = 0xfa,
|
||||
RSL_IE_IPAC_RTP_COMPR = 0xfb,
|
||||
RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc,
|
||||
RSL_IE_IPAC_RTP_MPLEX = 0xfd,
|
||||
RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe,
|
||||
};
|
||||
|
||||
/* Chapter 9.3.1 */
|
||||
#define RSL_CHAN_NR_MASK 0xf8
|
||||
#define RSL_CHAN_Bm_ACCHs 0x08
|
||||
#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */
|
||||
#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */
|
||||
#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */
|
||||
#define RSL_CHAN_BCCH 0x80
|
||||
#define RSL_CHAN_RACH 0x88
|
||||
#define RSL_CHAN_PCH_AGCH 0x90
|
||||
|
||||
/* Chapter 9.3.3 */
|
||||
#define RSL_ACT_TYPE_INITIAL 0x00
|
||||
#define RSL_ACT_TYPE_REACT 0x80
|
||||
#define RSL_ACT_INTRA_IMM_ASS 0x00
|
||||
#define RSL_ACT_INTRA_NORM_ASS 0x01
|
||||
#define RSL_ACT_INTER_ASYNC 0x02
|
||||
#define RSL_ACT_INTER_SYNC 0x03
|
||||
#define RSL_ACT_SECOND_ADD 0x04
|
||||
#define RSL_ACT_SECOND_MULTI 0x05
|
||||
|
||||
/* Chapter 9.3.6 */
|
||||
struct rsl_ie_chan_mode {
|
||||
uint8_t dtx_dtu;
|
||||
uint8_t spd_ind;
|
||||
uint8_t chan_rt;
|
||||
uint8_t chan_rate;
|
||||
} __attribute__ ((packed));
|
||||
#define RSL_CMOD_DTXu 0x01 /* uplink */
|
||||
#define RSL_CMOD_DTXd 0x02 /* downlink */
|
||||
enum rsl_cmod_spd {
|
||||
RSL_CMOD_SPD_SPEECH = 0x01,
|
||||
RSL_CMOD_SPD_DATA = 0x02,
|
||||
RSL_CMOD_SPD_SIGN = 0x03,
|
||||
};
|
||||
#define RSL_CMOD_CRT_SDCCH 0x01
|
||||
#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */
|
||||
#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */
|
||||
/* FIXME: More CRT types */
|
||||
/* Speech */
|
||||
#define RSL_CMOD_SP_GSM1 0x01
|
||||
#define RSL_CMOD_SP_GSM2 0x11
|
||||
#define RSL_CMOD_SP_GSM3 0x21
|
||||
/* Data */
|
||||
#define RSL_CMOD_SP_NT_14k5 0x58
|
||||
#define RSL_CMOD_SP_NT_12k0 0x50
|
||||
#define RSL_CMOD_SP_NT_6k0 0x51
|
||||
|
||||
/* Chapter 9.3.5 */
|
||||
struct rsl_ie_chan_ident {
|
||||
/* GSM 04.08 10.5.2.5 */
|
||||
struct {
|
||||
uint8_t iei;
|
||||
uint8_t chan_nr; /* enc_chan_nr */
|
||||
uint8_t oct3;
|
||||
uint8_t oct4;
|
||||
} chan_desc;
|
||||
#if 0 /* spec says we need this but Abissim doesn't use it */
|
||||
struct {
|
||||
uint8_t tag;
|
||||
uint8_t len;
|
||||
} mobile_alloc;
|
||||
#endif
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chapter 9.3.22 */
|
||||
#define RLL_CAUSE_T200_EXPIRED 0x01
|
||||
#define RLL_CAUSE_REEST_REQ 0x02
|
||||
#define RLL_CAUSE_UNSOL_UA_RESP 0x03
|
||||
#define RLL_CAUSE_UNSOL_DM_RESP 0x04
|
||||
#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05
|
||||
#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06
|
||||
#define RLL_CAUSE_SEQ_ERR 0x07
|
||||
#define RLL_CAUSE_UFRM_INC_PARAM 0x08
|
||||
#define RLL_CAUSE_SFRM_INC_PARAM 0x09
|
||||
#define RLL_CAUSE_IFRM_INC_MBITS 0x0a
|
||||
#define RLL_CAUSE_IFRM_INC_LEN 0x0b
|
||||
#define RLL_CAUSE_FRM_UNIMPL 0x0c
|
||||
#define RLL_CAUSE_SABM_MF 0x0d
|
||||
#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e
|
||||
|
||||
/* Chapter 9.3.26 */
|
||||
#define RSL_ERRCLS_NORMAL 0x00
|
||||
#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20
|
||||
#define RSL_ERRCLS_SERVICE_UNAVAIL 0x30
|
||||
#define RSL_ERRCLS_SERVICE_UNIMPL 0x40
|
||||
#define RSL_ERRCLS_INVAL_MSG 0x50
|
||||
#define RSL_ERRCLS_PROTO_ERROR 0x60
|
||||
#define RSL_ERRCLS_INTERWORKING 0x70
|
||||
|
||||
/* normal event */
|
||||
#define RSL_ERR_RADIO_IF_FAIL 0x00
|
||||
#define RSL_ERR_RADIO_LINK_FAIL 0x01
|
||||
#define RSL_ERR_HANDOVER_ACC_FAIL 0x02
|
||||
#define RSL_ERR_TALKER_ACC_FAIL 0x03
|
||||
#define RSL_ERR_OM_INTERVENTION 0x07
|
||||
#define RSL_ERR_NORMAL_UNSPEC 0x0f
|
||||
#define RSL_ERR_T_MSRFPCI_EXP 0x18
|
||||
/* resource unavailable */
|
||||
#define RSL_ERR_EQUIPMENT_FAIL 0x20
|
||||
#define RSL_ERR_RR_UNAVAIL 0x21
|
||||
#define RSL_ERR_TERR_CH_FAIL 0x22
|
||||
#define RSL_ERR_CCCH_OVERLOAD 0x23
|
||||
#define RSL_ERR_ACCH_OVERLOAD 0x24
|
||||
#define RSL_ERR_PROCESSOR_OVERLOAD 0x25
|
||||
#define RSL_ERR_RES_UNAVAIL 0x2f
|
||||
/* service or option not available */
|
||||
#define RSL_ERR_TRANSC_UNAVAIL 0x30
|
||||
#define RSL_ERR_SERV_OPT_UNAVAIL 0x3f
|
||||
/* service or option not implemented */
|
||||
#define RSL_ERR_ENCR_UNIMPL 0x40
|
||||
#define RSL_ERR_SERV_OPT_UNIMPL 0x4f
|
||||
/* invalid message */
|
||||
#define RSL_ERR_RCH_ALR_ACTV_ALLOC 0x50
|
||||
#define RSL_ERR_INVALID_MESSAGE 0x5f
|
||||
/* protocol error */
|
||||
#define RSL_ERR_MSG_DISCR 0x60
|
||||
#define RSL_ERR_MSG_TYPE 0x61
|
||||
#define RSL_ERR_MSG_SEQ 0x62
|
||||
#define RSL_ERR_IE_ERROR 0x63
|
||||
#define RSL_ERR_MAND_IE_ERROR 0x64
|
||||
#define RSL_ERR_OPT_IE_ERROR 0x65
|
||||
#define RSL_ERR_IE_NONEXIST 0x66
|
||||
#define RSL_ERR_IE_LENGTH 0x67
|
||||
#define RSL_ERR_IE_CONTENT 0x68
|
||||
#define RSL_ERR_PROTO 0x6f
|
||||
/* interworking */
|
||||
#define RSL_ERR_INTERWORKING 0x7f
|
||||
|
||||
/* Chapter 9.3.30 */
|
||||
#define RSL_SYSTEM_INFO_8 0x00
|
||||
#define RSL_SYSTEM_INFO_1 0x01
|
||||
#define RSL_SYSTEM_INFO_2 0x02
|
||||
#define RSL_SYSTEM_INFO_3 0x03
|
||||
#define RSL_SYSTEM_INFO_4 0x04
|
||||
#define RSL_SYSTEM_INFO_5 0x05
|
||||
#define RSL_SYSTEM_INFO_6 0x06
|
||||
#define RSL_SYSTEM_INFO_7 0x07
|
||||
#define RSL_SYSTEM_INFO_16 0x08
|
||||
#define RSL_SYSTEM_INFO_17 0x09
|
||||
#define RSL_SYSTEM_INFO_2bis 0x0a
|
||||
#define RSL_SYSTEM_INFO_2ter 0x0b
|
||||
#define RSL_SYSTEM_INFO_5bis 0x0d
|
||||
#define RSL_SYSTEM_INFO_5ter 0x0e
|
||||
#define RSL_SYSTEM_INFO_10 0x0f
|
||||
#define REL_EXT_MEAS_ORDER 0x47
|
||||
#define RSL_MEAS_INFO 0x48
|
||||
#define RSL_SYSTEM_INFO_13 0x28
|
||||
#define RSL_SYSTEM_INFO_2quater 0x29
|
||||
#define RSL_SYSTEM_INFO_9 0x2a
|
||||
#define RSL_SYSTEM_INFO_18 0x2b
|
||||
#define RSL_SYSTEM_INFO_19 0x2c
|
||||
#define RSL_SYSTEM_INFO_20 0x2d
|
||||
|
||||
/* Chapter 9.3.40 */
|
||||
#define RSL_CHANNEED_ANY 0x00
|
||||
#define RSL_CHANNEED_SDCCH 0x01
|
||||
#define RSL_CHANNEED_TCH_F 0x02
|
||||
#define RSL_CHANNEED_TCH_ForH 0x03
|
||||
|
||||
/* Chapter 3.3.2.3 Brocast control channel */
|
||||
/* CCCH-CONF, NC is not combined */
|
||||
#define RSL_BCCH_CCCH_CONF_1_NC 0x00
|
||||
#define RSL_BCCH_CCCH_CONF_1_C 0x01
|
||||
#define RSL_BCCH_CCCH_CONF_2_NC 0x02
|
||||
#define RSL_BCCH_CCCH_CONF_3_NC 0x04
|
||||
#define RSL_BCCH_CCCH_CONF_4_NC 0x06
|
||||
|
||||
/* BS-PA-MFRMS */
|
||||
#define RSL_BS_PA_MFRMS_2 0x00
|
||||
#define RSL_BS_PA_MFRMS_3 0x01
|
||||
#define RSL_BS_PA_MFRMS_4 0x02
|
||||
#define RSL_BS_PA_MFRMS_5 0x03
|
||||
#define RSL_BS_PA_MFRMS_6 0x04
|
||||
#define RSL_BS_PA_MFRMS_7 0x05
|
||||
#define RSL_BS_PA_MFRMS_8 0x06
|
||||
#define RSL_BS_PA_MFRMS_9 0x07
|
||||
|
||||
/* RSL_IE_IPAC_RTP_PAYLOAD[2] */
|
||||
enum rsl_ipac_rtp_payload {
|
||||
RSL_IPAC_RTP_GSM = 1,
|
||||
RSL_IPAC_RTP_EFR,
|
||||
RSL_IPAC_RTP_AMR,
|
||||
RSL_IPAC_RTP_CSD,
|
||||
RSL_IPAC_RTP_MUX,
|
||||
};
|
||||
|
||||
/* RSL_IE_IPAC_SPEECH_MODE, lower four bits */
|
||||
enum rsl_ipac_speech_mode_s {
|
||||
RSL_IPAC_SPEECH_GSM_FR = 0, /* GSM FR (Type 1, FS) */
|
||||
RSL_IPAC_SPEECH_GSM_EFR = 1, /* GSM EFR (Type 2, FS) */
|
||||
RSL_IPAC_SPEECH_GSM_AMR_FR = 2, /* GSM AMR/FR (Type 3, FS) */
|
||||
RSL_IPAC_SPEECH_GSM_HR = 3, /* GSM HR (Type 1, HS) */
|
||||
RSL_IPAC_SPEECH_GSM_AMR_HR = 5, /* GSM AMR/hr (Type 3, HS) */
|
||||
RSL_IPAC_SPEECH_AS_RTP = 0xf, /* As specified by RTP Payload IE */
|
||||
};
|
||||
/* RSL_IE_IPAC_SPEECH_MODE, upper four bits */
|
||||
enum rsl_ipac_speech_mode_m {
|
||||
RSL_IPAC_SPEECH_M_RXTX = 0, /* Send and Receive */
|
||||
RSL_IPAC_SPEECH_M_RX = 1, /* Receive only */
|
||||
RSL_IPAC_SPEECH_M_TX = 2, /* Send only */
|
||||
};
|
||||
|
||||
/* RSL_IE_IPAC_RTP_CSD_FMT, lower four bits */
|
||||
enum rsl_ipac_rtp_csd_format_d {
|
||||
RSL_IPAC_RTP_CSD_EXT_TRAU = 0,
|
||||
RSL_IPAC_RTP_CSD_NON_TRAU = 1,
|
||||
RSL_IPAC_RTP_CSD_TRAU_BTS = 2,
|
||||
RSL_IPAC_RTP_CSD_IWF_FREE = 3,
|
||||
};
|
||||
/* RSL_IE_IPAC_RTP_CSD_FMT, upper four bits */
|
||||
enum rsl_ipac_rtp_csd_format_ir {
|
||||
RSL_IPAC_RTP_CSD_IR_8k = 0,
|
||||
RSL_IPAC_RTP_CSD_IR_16k = 1,
|
||||
RSL_IPAC_RTP_CSD_IR_32k = 2,
|
||||
RSL_IPAC_RTP_CSD_IR_64k = 3,
|
||||
};
|
||||
|
||||
/* Siemens vendor-specific RSL extensions */
|
||||
struct rsl_mrpci {
|
||||
uint8_t power_class:3,
|
||||
vgcs_capable:1,
|
||||
vbs_capable:1,
|
||||
gsm_phase:2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum rsl_mrpci_pwrclass {
|
||||
RSL_MRPCI_PWRC_1 = 0,
|
||||
RSL_MRPCI_PWRC_2 = 1,
|
||||
RSL_MRPCI_PWRC_3 = 2,
|
||||
RSL_MRPCI_PWRC_4 = 3,
|
||||
RSL_MRPCI_PWRC_5 = 4,
|
||||
};
|
||||
enum rsl_mrpci_phase {
|
||||
RSL_MRPCI_PHASE_1 = 0,
|
||||
/* reserved */
|
||||
RSL_MRPCI_PHASE_2 = 2,
|
||||
RSL_MRPCI_PHASE_2PLUS = 3,
|
||||
};
|
||||
|
||||
|
||||
#endif /* PROTO_GSM_08_58_H */
|
|
@ -0,0 +1,691 @@
|
|||
#ifndef PROTO_GSM_12_21_H
|
||||
#define PROTO_GSM_12_21_H
|
||||
|
||||
/* GSM Network Management messages on the A-bis interface
|
||||
* 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
|
||||
|
||||
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocore/tlv.h>
|
||||
|
||||
/* generic header in front of every OML message according to TS 08.59 */
|
||||
struct abis_om_hdr {
|
||||
uint8_t mdisc;
|
||||
uint8_t placement;
|
||||
uint8_t sequence;
|
||||
uint8_t length;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define ABIS_OM_MDISC_FOM 0x80
|
||||
#define ABIS_OM_MDISC_MMI 0x40
|
||||
#define ABIS_OM_MDISC_TRAU 0x20
|
||||
#define ABIS_OM_MDISC_MANUF 0x10
|
||||
#define ABIS_OM_PLACEMENT_ONLY 0x80
|
||||
#define ABIS_OM_PLACEMENT_FIRST 0x40
|
||||
#define ABIS_OM_PLACEMENT_MIDDLE 0x20
|
||||
#define ABIS_OM_PLACEMENT_LAST 0x10
|
||||
|
||||
struct abis_om_obj_inst {
|
||||
uint8_t bts_nr;
|
||||
uint8_t trx_nr;
|
||||
uint8_t ts_nr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct abis_om_fom_hdr {
|
||||
uint8_t msg_type;
|
||||
uint8_t obj_class;
|
||||
struct abis_om_obj_inst obj_inst;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr))
|
||||
|
||||
/* Section 9.1: Message Types */
|
||||
enum abis_nm_msgtype {
|
||||
/* SW Download Management Messages */
|
||||
NM_MT_LOAD_INIT = 0x01,
|
||||
NM_MT_LOAD_INIT_ACK,
|
||||
NM_MT_LOAD_INIT_NACK,
|
||||
NM_MT_LOAD_SEG,
|
||||
NM_MT_LOAD_SEG_ACK,
|
||||
NM_MT_LOAD_ABORT,
|
||||
NM_MT_LOAD_END,
|
||||
NM_MT_LOAD_END_ACK,
|
||||
NM_MT_LOAD_END_NACK,
|
||||
NM_MT_SW_ACT_REQ, /* BTS->BSC */
|
||||
NM_MT_SW_ACT_REQ_ACK,
|
||||
NM_MT_SW_ACT_REQ_NACK,
|
||||
NM_MT_ACTIVATE_SW, /* BSC->BTS */
|
||||
NM_MT_ACTIVATE_SW_ACK,
|
||||
NM_MT_ACTIVATE_SW_NACK,
|
||||
NM_MT_SW_ACTIVATED_REP, /* 0x10 */
|
||||
/* A-bis Interface Management Messages */
|
||||
NM_MT_ESTABLISH_TEI = 0x21,
|
||||
NM_MT_ESTABLISH_TEI_ACK,
|
||||
NM_MT_ESTABLISH_TEI_NACK,
|
||||
NM_MT_CONN_TERR_SIGN,
|
||||
NM_MT_CONN_TERR_SIGN_ACK,
|
||||
NM_MT_CONN_TERR_SIGN_NACK,
|
||||
NM_MT_DISC_TERR_SIGN,
|
||||
NM_MT_DISC_TERR_SIGN_ACK,
|
||||
NM_MT_DISC_TERR_SIGN_NACK,
|
||||
NM_MT_CONN_TERR_TRAF,
|
||||
NM_MT_CONN_TERR_TRAF_ACK,
|
||||
NM_MT_CONN_TERR_TRAF_NACK,
|
||||
NM_MT_DISC_TERR_TRAF,
|
||||
NM_MT_DISC_TERR_TRAF_ACK,
|
||||
NM_MT_DISC_TERR_TRAF_NACK,
|
||||
/* Transmission Management Messages */
|
||||
NM_MT_CONN_MDROP_LINK = 0x31,
|
||||
NM_MT_CONN_MDROP_LINK_ACK,
|
||||
NM_MT_CONN_MDROP_LINK_NACK,
|
||||
NM_MT_DISC_MDROP_LINK,
|
||||
NM_MT_DISC_MDROP_LINK_ACK,
|
||||
NM_MT_DISC_MDROP_LINK_NACK,
|
||||
/* Air Interface Management Messages */
|
||||
NM_MT_SET_BTS_ATTR = 0x41,
|
||||
NM_MT_SET_BTS_ATTR_ACK,
|
||||
NM_MT_SET_BTS_ATTR_NACK,
|
||||
NM_MT_SET_RADIO_ATTR,
|
||||
NM_MT_SET_RADIO_ATTR_ACK,
|
||||
NM_MT_SET_RADIO_ATTR_NACK,
|
||||
NM_MT_SET_CHAN_ATTR,
|
||||
NM_MT_SET_CHAN_ATTR_ACK,
|
||||
NM_MT_SET_CHAN_ATTR_NACK,
|
||||
/* Test Management Messages */
|
||||
NM_MT_PERF_TEST = 0x51,
|
||||
NM_MT_PERF_TEST_ACK,
|
||||
NM_MT_PERF_TEST_NACK,
|
||||
NM_MT_TEST_REP,
|
||||
NM_MT_SEND_TEST_REP,
|
||||
NM_MT_SEND_TEST_REP_ACK,
|
||||
NM_MT_SEND_TEST_REP_NACK,
|
||||
NM_MT_STOP_TEST,
|
||||
NM_MT_STOP_TEST_ACK,
|
||||
NM_MT_STOP_TEST_NACK,
|
||||
/* State Management and Event Report Messages */
|
||||
NM_MT_STATECHG_EVENT_REP = 0x61,
|
||||
NM_MT_FAILURE_EVENT_REP,
|
||||
NM_MT_STOP_EVENT_REP,
|
||||
NM_MT_STOP_EVENT_REP_ACK,
|
||||
NM_MT_STOP_EVENT_REP_NACK,
|
||||
NM_MT_REST_EVENT_REP,
|
||||
NM_MT_REST_EVENT_REP_ACK,
|
||||
NM_MT_REST_EVENT_REP_NACK,
|
||||
NM_MT_CHG_ADM_STATE,
|
||||
NM_MT_CHG_ADM_STATE_ACK,
|
||||
NM_MT_CHG_ADM_STATE_NACK,
|
||||
NM_MT_CHG_ADM_STATE_REQ,
|
||||
NM_MT_CHG_ADM_STATE_REQ_ACK,
|
||||
NM_MT_CHG_ADM_STATE_REQ_NACK,
|
||||
NM_MT_REP_OUTST_ALARMS = 0x93,
|
||||
NM_MT_REP_OUTST_ALARMS_ACK,
|
||||
NM_MT_REP_OUTST_ALARMS_NACK,
|
||||
/* Equipment Management Messages */
|
||||
NM_MT_CHANGEOVER = 0x71,
|
||||
NM_MT_CHANGEOVER_ACK,
|
||||
NM_MT_CHANGEOVER_NACK,
|
||||
NM_MT_OPSTART,
|
||||
NM_MT_OPSTART_ACK,
|
||||
NM_MT_OPSTART_NACK,
|
||||
NM_MT_REINIT,
|
||||
NM_MT_REINIT_ACK,
|
||||
NM_MT_REINIT_NACK,
|
||||
NM_MT_SET_SITE_OUT, /* BS11: get alarm ?!? */
|
||||
NM_MT_SET_SITE_OUT_ACK,
|
||||
NM_MT_SET_SITE_OUT_NACK,
|
||||
NM_MT_CHG_HW_CONF = 0x90,
|
||||
NM_MT_CHG_HW_CONF_ACK,
|
||||
NM_MT_CHG_HW_CONF_NACK,
|
||||
/* Measurement Management Messages */
|
||||
NM_MT_MEAS_RES_REQ = 0x8a,
|
||||
NM_MT_MEAS_RES_RESP,
|
||||
NM_MT_STOP_MEAS,
|
||||
NM_MT_START_MEAS,
|
||||
/* Other Messages */
|
||||
NM_MT_GET_ATTR = 0x81,
|
||||
NM_MT_GET_ATTR_RESP,
|
||||
NM_MT_GET_ATTR_NACK,
|
||||
NM_MT_SET_ALARM_THRES,
|
||||
NM_MT_SET_ALARM_THRES_ACK,
|
||||
NM_MT_SET_ALARM_THRES_NACK,
|
||||
};
|
||||
|
||||
enum abis_nm_msgtype_bs11 {
|
||||
NM_MT_BS11_RESET_RESOURCE = 0x74,
|
||||
|
||||
NM_MT_BS11_BEGIN_DB_TX = 0xa3,
|
||||
NM_MT_BS11_BEGIN_DB_TX_ACK,
|
||||
NM_MT_BS11_BEGIN_DB_TX_NACK,
|
||||
NM_MT_BS11_END_DB_TX = 0xa6,
|
||||
NM_MT_BS11_END_DB_TX_ACK,
|
||||
NM_MT_BS11_END_DB_TX_NACK,
|
||||
NM_MT_BS11_CREATE_OBJ = 0xa9,
|
||||
NM_MT_BS11_CREATE_OBJ_ACK,
|
||||
NM_MT_BS11_CREATE_OBJ_NACK,
|
||||
NM_MT_BS11_DELETE_OBJ = 0xac,
|
||||
NM_MT_BS11_DELETE_OBJ_ACK,
|
||||
NM_MT_BS11_DELETE_OBJ_NACK,
|
||||
|
||||
NM_MT_BS11_SET_ATTR = 0xd0,
|
||||
NM_MT_BS11_SET_ATTR_ACK,
|
||||
NM_MT_BS11_SET_ATTR_NACK,
|
||||
NM_MT_BS11_LMT_SESSION = 0xdc,
|
||||
|
||||
NM_MT_BS11_GET_STATE = 0xe3,
|
||||
NM_MT_BS11_GET_STATE_ACK,
|
||||
NM_MT_BS11_LMT_LOGON = 0xe5,
|
||||
NM_MT_BS11_LMT_LOGON_ACK,
|
||||
NM_MT_BS11_RESTART = 0xe7,
|
||||
NM_MT_BS11_RESTART_ACK,
|
||||
NM_MT_BS11_DISCONNECT = 0xe9,
|
||||
NM_MT_BS11_DISCONNECT_ACK,
|
||||
NM_MT_BS11_LMT_LOGOFF = 0xec,
|
||||
NM_MT_BS11_LMT_LOGOFF_ACK,
|
||||
NM_MT_BS11_RECONNECT = 0xf1,
|
||||
NM_MT_BS11_RECONNECT_ACK,
|
||||
};
|
||||
|
||||
enum abis_nm_msgtype_ipacc {
|
||||
NM_MT_IPACC_RESTART = 0x87,
|
||||
NM_MT_IPACC_RESTART_ACK,
|
||||
NM_MT_IPACC_RESTART_NACK,
|
||||
NM_MT_IPACC_RSL_CONNECT = 0xe0,
|
||||
NM_MT_IPACC_RSL_CONNECT_ACK,
|
||||
NM_MT_IPACC_RSL_CONNECT_NACK,
|
||||
NM_MT_IPACC_RSL_DISCONNECT = 0xe3,
|
||||
NM_MT_IPACC_RSL_DISCONNECT_ACK,
|
||||
NM_MT_IPACC_RSL_DISCONNECT_NACK,
|
||||
NM_MT_IPACC_CONN_TRAF = 0xe6,
|
||||
NM_MT_IPACC_CONN_TRAF_ACK,
|
||||
NM_MT_IPACC_CONN_TRAF_NACK,
|
||||
NM_MT_IPACC_DEF_BOOT_SW = 0xec,
|
||||
NM_MT_IPACC_DEF_BOOT_SW_ACK,
|
||||
MN_MT_IPACC_DEF_BOOT_SW_NACK,
|
||||
NM_MT_IPACC_SET_NVATTR = 0xef,
|
||||
NM_MT_IPACC_SET_NVATTR_ACK,
|
||||
NM_MT_IPACC_SET_NVATTR_NACK,
|
||||
NM_MT_IPACC_GET_NVATTR = 0xf2,
|
||||
NM_MT_IPACC_GET_NVATTR_ACK,
|
||||
NM_MT_IPACC_GET_NVATTR_NACK,
|
||||
NM_MT_IPACC_SET_ATTR = 0xf5,
|
||||
NM_MT_IPACC_SET_ATTR_ACK,
|
||||
NM_MT_IPACC_SET_ATTR_NACK,
|
||||
};
|
||||
|
||||
enum abis_nm_bs11_cell_alloc {
|
||||
NM_BS11_CANR_GSM = 0x00,
|
||||
NM_BS11_CANR_DCS1800 = 0x01,
|
||||
};
|
||||
|
||||
/* Section 9.2: Object Class */
|
||||
enum abis_nm_obj_class {
|
||||
NM_OC_SITE_MANAGER = 0x00,
|
||||
NM_OC_BTS,
|
||||
NM_OC_RADIO_CARRIER,
|
||||
NM_OC_CHANNEL,
|
||||
NM_OC_BASEB_TRANSC,
|
||||
/* RFU: 05-FE */
|
||||
|
||||
NM_OC_IPAC_E1_TRUNK = 0x0e,
|
||||
NM_OC_IPAC_E1_PORT = 0x0f,
|
||||
NM_OC_IPAC_E1_CHAN = 0x10,
|
||||
NM_OC_IPAC_CLK_MODULE = 0x22,
|
||||
|
||||
NM_OC_BS11_ADJC = 0xa0,
|
||||
NM_OC_BS11_HANDOVER = 0xa1,
|
||||
NM_OC_BS11_PWR_CTRL = 0xa2,
|
||||
NM_OC_BS11_BTSE = 0xa3, /* LMT? */
|
||||
NM_OC_BS11_RACK = 0xa4,
|
||||
NM_OC_BS11 = 0xa5, /* 01: ALCO */
|
||||
NM_OC_BS11_TEST = 0xa6,
|
||||
NM_OC_BS11_ENVABTSE = 0xa8,
|
||||
NM_OC_BS11_BPORT = 0xa9,
|
||||
|
||||
NM_OC_GPRS_NSE = 0xf0,
|
||||
NM_OC_GPRS_CELL = 0xf1,
|
||||
NM_OC_GPRS_NSVC = 0xf2,
|
||||
|
||||
NM_OC_NULL = 0xff,
|
||||
};
|
||||
|
||||
/* Section 9.4: Attributes */
|
||||
enum abis_nm_attr {
|
||||
NM_ATT_ABIS_CHANNEL = 0x01,
|
||||
NM_ATT_ADD_INFO,
|
||||
NM_ATT_ADD_TEXT,
|
||||
NM_ATT_ADM_STATE,
|
||||
NM_ATT_ARFCN_LIST,
|
||||
NM_ATT_AUTON_REPORT,
|
||||
NM_ATT_AVAIL_STATUS,
|
||||
NM_ATT_BCCH_ARFCN,
|
||||
NM_ATT_BSIC,
|
||||
NM_ATT_BTS_AIR_TIMER,
|
||||
NM_ATT_CCCH_L_I_P,
|
||||
NM_ATT_CCCH_L_T,
|
||||
NM_ATT_CHAN_COMB,
|
||||
NM_ATT_CONN_FAIL_CRIT,
|
||||
NM_ATT_DEST,
|
||||
/* res */
|
||||
NM_ATT_EVENT_TYPE = 0x11, /* BS11: file data ?!? */
|
||||
NM_ATT_FILE_ID,
|
||||
NM_ATT_FILE_VERSION,
|
||||
NM_ATT_GSM_TIME,
|
||||
NM_ATT_HSN,
|
||||
NM_ATT_HW_CONFIG,
|
||||
NM_ATT_HW_DESC,
|
||||
NM_ATT_INTAVE_PARAM,
|
||||
NM_ATT_INTERF_BOUND,
|
||||
NM_ATT_LIST_REQ_ATTR,
|
||||
NM_ATT_MAIO,
|
||||
NM_ATT_MANUF_STATE,
|
||||
NM_ATT_MANUF_THRESH,
|
||||
NM_ATT_MANUF_ID,
|
||||
NM_ATT_MAX_TA,
|
||||
NM_ATT_MDROP_LINK, /* 0x20 */
|
||||
NM_ATT_MDROP_NEXT,
|
||||
NM_ATT_NACK_CAUSES,
|
||||
NM_ATT_NY1,
|
||||
NM_ATT_OPER_STATE,
|
||||
NM_ATT_OVERL_PERIOD,
|
||||
NM_ATT_PHYS_CONF,
|
||||
NM_ATT_POWER_CLASS,
|
||||
NM_ATT_POWER_THRESH,
|
||||
NM_ATT_PROB_CAUSE,
|
||||
NM_ATT_RACH_B_THRESH,
|
||||
NM_ATT_LDAVG_SLOTS,
|
||||
NM_ATT_RAD_SUBC,
|
||||
NM_ATT_RF_MAXPOWR_R,
|
||||
NM_ATT_SITE_INPUTS,
|
||||
NM_ATT_SITE_OUTPUTS,
|
||||
NM_ATT_SOURCE, /* 0x30 */
|
||||
NM_ATT_SPEC_PROB,
|
||||
NM_ATT_START_TIME,
|
||||
NM_ATT_T200,
|
||||
NM_ATT_TEI,
|
||||
NM_ATT_TEST_DUR,
|
||||
NM_ATT_TEST_NO,
|
||||
NM_ATT_TEST_REPORT,
|
||||
NM_ATT_VSWR_THRESH,
|
||||
NM_ATT_WINDOW_SIZE,
|
||||
/* Res */
|
||||
NM_ATT_BS11_RSSI_OFFS = 0x3d,
|
||||
NM_ATT_BS11_TXPWR = 0x3e,
|
||||
NM_ATT_BS11_DIVERSITY = 0x3f,
|
||||
/* Res */
|
||||
NM_ATT_TSC = 0x40,
|
||||
NM_ATT_SW_CONFIG,
|
||||
NM_ATT_SW_DESCR,
|
||||
NM_ATT_SEVERITY,
|
||||
NM_ATT_GET_ARI,
|
||||
NM_ATT_HW_CONF_CHG,
|
||||
NM_ATT_OUTST_ALARM,
|
||||
NM_ATT_FILE_DATA,
|
||||
NM_ATT_MEAS_RES,
|
||||
NM_ATT_MEAS_TYPE,
|
||||
|
||||
NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c,
|
||||
NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f,
|
||||
|
||||
NM_ATT_BS11_ESN_PCB_SERIAL = 0x55,
|
||||
NM_ATT_BS11_EXCESSIVE_DISTANCE = 0x58,
|
||||
|
||||
NM_ATT_BS11_ALL_TEST_CATG = 0x60,
|
||||
NM_ATT_BS11_BTSLS_HOPPING,
|
||||
NM_ATT_BS11_CELL_ALLOC_NR,
|
||||
NM_ATT_BS11_CELL_GLOBAL_ID,
|
||||
NM_ATT_BS11_ENA_INTERF_CLASS = 0x66,
|
||||
NM_ATT_BS11_ENA_INT_INTEC_HANDO = 0x67,
|
||||
NM_ATT_BS11_ENA_INT_INTRC_HANDO = 0x68,
|
||||
NM_ATT_BS11_ENA_MS_PWR_CTRL = 0x69,
|
||||
NM_ATT_BS11_ENA_PWR_BDGT_HO = 0x6a,
|
||||
NM_ATT_BS11_ENA_PWR_CTRL_RLFW = 0x6b,
|
||||
NM_ATT_BS11_ENA_RXLEV_HO = 0x6c,
|
||||
NM_ATT_BS11_ENA_RXQUAL_HO = 0x6d,
|
||||
NM_ATT_BS11_FACCH_QUAL = 0x6e,
|
||||
|
||||
NM_ATT_IPACC_DST_IP = 0x80,
|
||||
NM_ATT_IPACC_DST_IP_PORT = 0x81,
|
||||
NM_ATT_IPACC_SSRC = 0x82,
|
||||
NM_ATT_IPACC_RTP_PAYLD_TYPE = 0x83,
|
||||
NM_ATT_IPACC_BASEB_ID = 0x84,
|
||||
NM_ATT_IPACC_STREAM_ID = 0x85,
|
||||
NM_ATT_IPACC_NV_FLAGS = 0x86,
|
||||
NM_ATT_IPACC_FREQ_CTRL = 0x87,
|
||||
NM_ATT_IPACC_PRIM_OML_CFG = 0x88,
|
||||
NM_ATT_IPACC_SEC_OML_CFG = 0x89,
|
||||
NM_ATT_IPACC_IP_IF_CFG = 0x8a, /* IP interface */
|
||||
NM_ATT_IPACC_IP_GW_CFG = 0x8b, /* IP gateway */
|
||||
NM_ATT_IPACC_IN_SERV_TIME = 0x8c,
|
||||
NM_ATT_IPACC_TRX_BTS_ASS = 0x8d,
|
||||
NM_ATT_IPACC_LOCATION = 0x8e, /* string describing location */
|
||||
NM_ATT_IPACC_PAGING_CFG = 0x8f,
|
||||
NM_ATT_IPACC_FILE_DATA = 0x90,
|
||||
NM_ATT_IPACC_UNIT_ID = 0x91, /* Site/BTS/TRX */
|
||||
NM_ATT_IPACC_PARENT_UNIT_ID = 0x92,
|
||||
NM_ATT_IPACC_UNIT_NAME = 0x93, /* default: nbts-<mac-as-string> */
|
||||
NM_ATT_IPACC_SNMP_CFG = 0x94,
|
||||
NM_ATT_IPACC_PRIM_OML_CFG_LIST = 0x95,
|
||||
NM_ATT_IPACC_PRIM_OML_FB_TOUT = 0x96,
|
||||
NM_ATT_IPACC_CUR_SW_CFG = 0x97,
|
||||
NM_ATT_IPACC_TIMING_BUS = 0x98,
|
||||
NM_ATT_IPACC_CGI = 0x99,
|
||||
NM_ATT_IPACC_RAC = 0x9a,
|
||||
NM_ATT_IPACC_OBJ_VERSION = 0x9b,
|
||||
NM_ATT_IPACC_GPRS_PAGING_CFG = 0x9c,
|
||||
NM_ATT_IPACC_NSEI = 0x9d,
|
||||
NM_ATT_IPACC_BVCI = 0x9e,
|
||||
NM_ATT_IPACC_NSVCI = 0x9f,
|
||||
NM_ATT_IPACC_NS_CFG = 0xa0,
|
||||
NM_ATT_IPACC_BSSGP_CFG = 0xa1,
|
||||
NM_ATT_IPACC_NS_LINK_CFG = 0xa2,
|
||||
NM_ATT_IPACC_RLC_CFG = 0xa3,
|
||||
NM_ATT_IPACC_ALM_THRESH_LIST = 0xa4,
|
||||
NM_ATT_IPACC_MONIT_VAL_LIST = 0xa5,
|
||||
NM_ATT_IPACC_TIB_CONTROL = 0xa6,
|
||||
NM_ATT_IPACC_SUPP_FEATURES = 0xa7,
|
||||
NM_ATT_IPACC_CODING_SCHEMES = 0xa8,
|
||||
NM_ATT_IPACC_RLC_CFG_2 = 0xa9,
|
||||
NM_ATT_IPACC_HEARTB_TOUT = 0xaa,
|
||||
NM_ATT_IPACC_UPTIME = 0xab,
|
||||
NM_ATT_IPACC_RLC_CFG_3 = 0xac,
|
||||
NM_ATT_IPACC_SSL_CFG = 0xad,
|
||||
NM_ATT_IPACC_SEC_POSSIBLE = 0xae,
|
||||
NM_ATT_IPACC_IML_SSL_STATE = 0xaf,
|
||||
NM_ATT_IPACC_REVOC_DATE = 0xb0,
|
||||
|
||||
|
||||
NM_ATT_BS11_RF_RES_IND_PER = 0x8f,
|
||||
|
||||
NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90,
|
||||
NM_ATT_BS11_ABIS_EXT_TIME = 0x91,
|
||||
NM_ATT_BS11_TIMER_HO_REQUEST = 0x92,
|
||||
NM_ATT_BS11_TIMER_NCELL = 0x93,
|
||||
NM_ATT_BS11_TSYNC = 0x94,
|
||||
NM_ATT_BS11_TTRAU = 0x95,
|
||||
NM_ATT_BS11_EMRG_CFG_MEMBER = 0x9b,
|
||||
NM_ATT_BS11_TRX_AREA = 0x9f,
|
||||
|
||||
NM_ATT_BS11_BCCH_RECONF = 0xd7,
|
||||
NM_ATT_BS11_BIT_ERR_THESH = 0xa0,
|
||||
NM_ATT_BS11_BOOT_SW_VERS = 0xa1,
|
||||
NM_ATT_BS11_CCLK_ACCURACY = 0xa3,
|
||||
NM_ATT_BS11_CCLK_TYPE = 0xa4,
|
||||
NM_ATT_BS11_INP_IMPEDANCE = 0xaa,
|
||||
NM_ATT_BS11_L1_PROT_TYPE = 0xab,
|
||||
NM_ATT_BS11_LINE_CFG = 0xac,
|
||||
NM_ATT_BS11_LI_PORT_1 = 0xad,
|
||||
NM_ATT_BS11_LI_PORT_2 = 0xae,
|
||||
|
||||
NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0,
|
||||
NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb,
|
||||
NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc,
|
||||
NM_ATT_BS11_SW_LOAD_STORED = 0xbd,
|
||||
|
||||
NM_ATT_BS11_VENDOR_NAME = 0xc1,
|
||||
NM_ATT_BS11_HOPPING_MODE = 0xc5,
|
||||
NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6,
|
||||
NM_ATT_BS11_LMT_LOGIN_TIME = 0xc7,
|
||||
NM_ATT_BS11_LMT_USER_ACC_LEV = 0xc8,
|
||||
NM_ATT_BS11_LMT_USER_NAME = 0xc9,
|
||||
|
||||
NM_ATT_BS11_L1_CONTROL_TS = 0xd8,
|
||||
NM_ATT_BS11_RADIO_MEAS_GRAN = 0xdc, /* in SACCH multiframes */
|
||||
NM_ATT_BS11_RADIO_MEAS_REP = 0xdd,
|
||||
|
||||
NM_ATT_BS11_SH_LAPD_INT_TIMER = 0xe8,
|
||||
|
||||
NM_ATT_BS11_BTS_STATE = 0xf0,
|
||||
NM_ATT_BS11_E1_STATE = 0xf1,
|
||||
NM_ATT_BS11_PLL = 0xf2,
|
||||
NM_ATT_BS11_RX_OFFSET = 0xf3,
|
||||
NM_ATT_BS11_ANT_TYPE = 0xf4,
|
||||
NM_ATT_BS11_PLL_MODE = 0xfc,
|
||||
NM_ATT_BS11_PASSWORD = 0xfd,
|
||||
};
|
||||
#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE
|
||||
|
||||
/* Section 9.4.4: Administrative State */
|
||||
enum abis_nm_adm_state {
|
||||
NM_STATE_LOCKED = 0x01,
|
||||
NM_STATE_UNLOCKED = 0x02,
|
||||
NM_STATE_SHUTDOWN = 0x03,
|
||||
NM_STATE_NULL = 0xff,
|
||||
};
|
||||
|
||||
/* Section 9.4.7: Administrative State */
|
||||
enum abis_nm_avail_state {
|
||||
NM_AVSTATE_IN_TEST = 1,
|
||||
NM_AVSTATE_POWER_OFF = 2,
|
||||
NM_AVSTATE_OFF_LINE = 3,
|
||||
NM_AVSTATE_DEPENDENCY = 5,
|
||||
NM_AVSTATE_DEGRADED = 6,
|
||||
NM_AVSTATE_NOT_INSTALLED= 7,
|
||||
NM_AVSTATE_OK = 0xff,
|
||||
};
|
||||
|
||||
enum abis_nm_op_state {
|
||||
NM_OPSTATE_DISABLED = 1,
|
||||
NM_OPSTATE_ENABLED = 2,
|
||||
NM_OPSTATE_NULL = 0xff,
|
||||
};
|
||||
|
||||
/* Section 9.4.13: Channel Combination */
|
||||
enum abis_nm_chan_comb {
|
||||
NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */
|
||||
NM_CHANC_TCHHalf = 0x01, /* TCH/H(0,1) + FACCH/H(0,1) +
|
||||
SACCH/TH(0,1) */
|
||||
NM_CHANC_TCHHalf2 = 0x02, /* TCH/H(0) + FACCH/H(0) + SACCH/TH(0) +
|
||||
TCH/H(1) */
|
||||
NM_CHANC_SDCCH = 0x03, /* SDCCH/8 + SACCH/8 */
|
||||
NM_CHANC_mainBCCH = 0x04, /* FCCH + SCH + BCCH + CCCH */
|
||||
NM_CHANC_BCCHComb = 0x05, /* FCCH + SCH + BCCH + CCCH + SDCCH/4 +
|
||||
SACCH/C4 */
|
||||
NM_CHANC_BCCH = 0x06, /* BCCH + CCCH */
|
||||
NM_CHANC_BCCH_CBCH = 0x07, /* CHANC_BCCHComb + CBCH */
|
||||
NM_CHANC_SDCCH_CBCH = 0x08, /* CHANC_SDCCH8 + CBCH */
|
||||
/* ip.access */
|
||||
NM_CHANC_IPAC_bPDCH = 0x0b, /* PBCCH + PCCCH + PDTCH/F + PACCH/F +
|
||||
PTCCH/F */
|
||||
NM_CHANC_IPAC_cPDCH = 0x0c, /* PBCCH + PDTCH/F + PACCH/F + PTCCH/F */
|
||||
NM_CHANC_IPAC_PDCH = 0x0d, /* PDTCH/F + PACCH/F + PTCCH/F */
|
||||
NM_CHANC_IPAC_TCHFull_PDCH = 0x80,
|
||||
NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81,
|
||||
};
|
||||
|
||||
/* Section 9.4.16: Event Type */
|
||||
enum abis_nm_event_type {
|
||||
NM_EVT_COMM_FAIL = 0x00,
|
||||
NM_EVT_QOS_FAIL = 0x01,
|
||||
NM_EVT_PROC_FAIL = 0x02,
|
||||
NM_EVT_EQUIP_FAIL = 0x03,
|
||||
NM_EVT_ENV_FAIL = 0x04,
|
||||
};
|
||||
|
||||
/* Section: 9.4.63: Perceived Severity */
|
||||
enum abis_nm_severity {
|
||||
NM_SEVER_CEASED = 0x00,
|
||||
NM_SEVER_CRITICAL = 0x01,
|
||||
NM_SEVER_MAJOR = 0x02,
|
||||
NM_SEVER_MINOR = 0x03,
|
||||
NM_SEVER_WARNING = 0x04,
|
||||
NM_SEVER_INDETERMINATE = 0x05,
|
||||
};
|
||||
|
||||
/* Section 9.4.43: Probable Cause Type */
|
||||
enum abis_nm_pcause_type {
|
||||
NM_PCAUSE_T_X721 = 0x01,
|
||||
NM_PCAUSE_T_GSM = 0x02,
|
||||
NM_PCAUSE_T_MANUF = 0x03,
|
||||
};
|
||||
|
||||
/* Section 9.4.36: NACK Causes */
|
||||
enum abis_nm_nack_cause {
|
||||
/* General Nack Causes */
|
||||
NM_NACK_INCORR_STRUCT = 0x01,
|
||||
NM_NACK_MSGTYPE_INVAL = 0x02,
|
||||
NM_NACK_OBJCLASS_INVAL = 0x05,
|
||||
NM_NACK_OBJCLASS_NOTSUPP = 0x06,
|
||||
NM_NACK_BTSNR_UNKN = 0x07,
|
||||
NM_NACK_TRXNR_UNKN = 0x08,
|
||||
NM_NACK_OBJINST_UNKN = 0x09,
|
||||
NM_NACK_ATTRID_INVAL = 0x0c,
|
||||
NM_NACK_ATTRID_NOTSUPP = 0x0d,
|
||||
NM_NACK_PARAM_RANGE = 0x0e,
|
||||
NM_NACK_ATTRLIST_INCONSISTENT = 0x0f,
|
||||
NM_NACK_SPEC_IMPL_NOTSUPP = 0x10,
|
||||
NM_NACK_CANT_PERFORM = 0x11,
|
||||
/* Specific Nack Causes */
|
||||
NM_NACK_RES_NOTIMPL = 0x19,
|
||||
NM_NACK_RES_NOTAVAIL = 0x1a,
|
||||
NM_NACK_FREQ_NOTAVAIL = 0x1b,
|
||||
NM_NACK_TEST_NOTSUPP = 0x1c,
|
||||
NM_NACK_CAPACITY_RESTR = 0x1d,
|
||||
NM_NACK_PHYSCFG_NOTPERFORM = 0x1e,
|
||||
NM_NACK_TEST_NOTINIT = 0x1f,
|
||||
NM_NACK_PHYSCFG_NOTRESTORE = 0x20,
|
||||
NM_NACK_TEST_NOSUCH = 0x21,
|
||||
NM_NACK_TEST_NOSTOP = 0x22,
|
||||
NM_NACK_MSGINCONSIST_PHYSCFG = 0x23,
|
||||
NM_NACK_FILE_INCOMPLETE = 0x25,
|
||||
NM_NACK_FILE_NOTAVAIL = 0x26,
|
||||
NM_NACK_FILE_NOTACTIVATE = 0x27,
|
||||
NM_NACK_REQ_NOT_GRANT = 0x28,
|
||||
NM_NACK_WAIT = 0x29,
|
||||
NM_NACK_NOTH_REPORT_EXIST = 0x2a,
|
||||
NM_NACK_MEAS_NOTSUPP = 0x2b,
|
||||
NM_NACK_MEAS_NOTSTART = 0x2c,
|
||||
};
|
||||
|
||||
/* Section 9.4.1 */
|
||||
struct abis_nm_channel {
|
||||
uint8_t attrib;
|
||||
uint8_t bts_port;
|
||||
uint8_t timeslot;
|
||||
uint8_t subslot;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */
|
||||
enum abis_bs11_objtype {
|
||||
BS11_OBJ_ALCO = 0x01,
|
||||
BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */
|
||||
BS11_OBJ_TRX1 = 0x03, /* only DEACTIVATE TRX1 */
|
||||
BS11_OBJ_CCLK = 0x04,
|
||||
BS11_OBJ_GPSU = 0x06,
|
||||
BS11_OBJ_LI = 0x07,
|
||||
BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/
|
||||
};
|
||||
|
||||
enum abis_bs11_trx_power {
|
||||
BS11_TRX_POWER_GSM_2W = 0x06,
|
||||
BS11_TRX_POWER_GSM_250mW= 0x07,
|
||||
BS11_TRX_POWER_GSM_80mW = 0x08,
|
||||
BS11_TRX_POWER_GSM_30mW = 0x09,
|
||||
BS11_TRX_POWER_DCS_3W = 0x0a,
|
||||
BS11_TRX_POWER_DCS_1W6 = 0x0b,
|
||||
BS11_TRX_POWER_DCS_500mW= 0x0c,
|
||||
BS11_TRX_POWER_DCS_160mW= 0x0d,
|
||||
};
|
||||
|
||||
enum abis_bs11_li_pll_mode {
|
||||
BS11_LI_PLL_LOCKED = 2,
|
||||
BS11_LI_PLL_STANDALONE = 3,
|
||||
};
|
||||
|
||||
enum abis_bs11_line_cfg {
|
||||
BS11_LINE_CFG_STAR = 0x00,
|
||||
BS11_LINE_CFG_MULTIDROP = 0x01,
|
||||
BS11_LINE_CFG_LOOP = 0x02,
|
||||
};
|
||||
|
||||
enum abis_bs11_phase {
|
||||
BS11_STATE_SOFTWARE_RQD = 0x01,
|
||||
BS11_STATE_LOAD_SMU_INTENDED = 0x11,
|
||||
BS11_STATE_LOAD_SMU_SAFETY = 0x21,
|
||||
BS11_STATE_LOAD_FAILED = 0x31,
|
||||
BS11_STATE_LOAD_DIAGNOSTIC = 0x41,
|
||||
BS11_STATE_WARM_UP = 0x51,
|
||||
BS11_STATE_WARM_UP_2 = 0x52,
|
||||
BS11_STATE_WAIT_MIN_CFG = 0x62,
|
||||
BS11_STATE_MAINTENANCE = 0x72,
|
||||
BS11_STATE_LOAD_MBCCU = 0x92,
|
||||
BS11_STATE_WAIT_MIN_CFG_2 = 0xA2,
|
||||
BS11_STATE_NORMAL = 0x03,
|
||||
BS11_STATE_ABIS_LOAD = 0x13,
|
||||
};
|
||||
|
||||
enum abis_nm_ipacc_test_no {
|
||||
NM_IPACC_TESTNO_RLOOP_ANT = 0x01,
|
||||
NM_IPACC_TESTNO_RLOOP_XCVR = 0x02,
|
||||
NM_IPACC_TESTNO_FUNC_OBJ = 0x03,
|
||||
NM_IPACC_TESTNO_CHAN_USAGE = 0x40,
|
||||
NM_IPACC_TESTNO_BCCH_CHAN_USAGE = 0x41,
|
||||
NM_IPACC_TESTNO_FREQ_SYNC = 0x42,
|
||||
NM_IPACC_TESTNO_BCCH_INFO = 0x43,
|
||||
NM_IPACC_TESTNO_TX_BEACON = 0x44,
|
||||
NM_IPACC_TESTNO_SYSINFO_MONITOR = 0x45,
|
||||
NM_IPACC_TESTNO_BCCCH_MONITOR = 0x46,
|
||||
};
|
||||
|
||||
/* first byte after length inside NM_ATT_TEST_REPORT */
|
||||
enum abis_nm_ipacc_test_res {
|
||||
NM_IPACC_TESTRES_SUCCESS = 0,
|
||||
NM_IPACC_TESTRES_TIMEOUT = 1,
|
||||
NM_IPACC_TESTRES_NO_CHANS = 2,
|
||||
NM_IPACC_TESTRES_PARTIAL = 3,
|
||||
NM_IPACC_TESTRES_STOPPED = 4,
|
||||
};
|
||||
|
||||
/* internal IE inside NM_ATT_TEST_REPORT */
|
||||
enum abis_nm_ipacc_testres_ie {
|
||||
NM_IPACC_TR_IE_FREQ_ERR_LIST = 3,
|
||||
NM_IPACC_TR_IE_CHAN_USAGE = 4,
|
||||
NM_IPACC_TR_IE_BCCH_INFO = 6,
|
||||
NM_IPACC_TR_IE_RESULT_DETAILS = 8,
|
||||
NM_IPACC_TR_IE_FREQ_ERR = 18,
|
||||
};
|
||||
|
||||
enum ipac_eie {
|
||||
NM_IPAC_EIE_ARFCN_WHITE = 0x01,
|
||||
NM_IPAC_EIE_ARFCH_BLACK = 0x02,
|
||||
NM_IPAC_EIE_FREQ_ERR_LIST = 0x03,
|
||||
NM_IPAC_EIE_CHAN_USE_LIST = 0x04,
|
||||
NM_IPAC_EIE_BCCH_INFO_TYPE = 0x05,
|
||||
NM_IPAC_EIE_BCCH_INFO = 0x06,
|
||||
/* FIXME */
|
||||
};
|
||||
|
||||
enum ipac_bcch_info_type {
|
||||
IPAC_BINF_RXLEV = (1 << 8),
|
||||
IPAC_BINF_RXQUAL = (1 << 9),
|
||||
IPAC_BINF_FREQ_ERR_QUAL = (1 << 10),
|
||||
IPAC_BINF_FRAME_OFFSET = (1 << 11),
|
||||
IPAC_BINF_FRAME_NR_OFFSET = (1 << 12),
|
||||
IPAC_BINF_BSIC = (1 << 13),
|
||||
IPAC_BINF_CGI = (1 << 14),
|
||||
IPAC_BINF_NEIGH_BA_SI2 = (1 << 15),
|
||||
IPAC_BINF_NEIGH_BA_SI2bis = (1 << 0),
|
||||
IPAC_BINF_NEIGH_BA_SI2ter = (1 << 1),
|
||||
IPAC_BINF_CELL_ALLOC = (1 << 2),
|
||||
};
|
||||
|
||||
#endif /* PROTO_GSM_12_21_H */
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _BSC_SELECT_H
|
||||
#define _BSC_SELECT_H
|
||||
|
||||
#include "linuxlist.h"
|
||||
|
||||
#define BSC_FD_READ 0x0001
|
||||
#define BSC_FD_WRITE 0x0002
|
||||
#define BSC_FD_EXCEPT 0x0004
|
||||
|
||||
struct bsc_fd {
|
||||
struct llist_head list;
|
||||
int fd;
|
||||
unsigned int when;
|
||||
int (*cb)(struct bsc_fd *fd, unsigned int what);
|
||||
void *data;
|
||||
unsigned int priv_nr;
|
||||
};
|
||||
|
||||
int bsc_register_fd(struct bsc_fd *fd);
|
||||
void bsc_unregister_fd(struct bsc_fd *fd);
|
||||
int bsc_select_main(int polling);
|
||||
#endif /* _BSC_SELECT_H */
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef OSMOCORE_SIGNAL_H
|
||||
#define OSMOCORE_SIGNAL_H
|
||||
|
||||
typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data);
|
||||
|
||||
|
||||
/* Management */
|
||||
int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
|
||||
void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
|
||||
|
||||
/* Dispatch */
|
||||
void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data);
|
||||
|
||||
#endif /* OSMOCORE_SIGNAL_H */
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef _STATISTICS_H
|
||||
#define _STATISTICS_H
|
||||
|
||||
struct counter {
|
||||
struct llist_head list;
|
||||
const char *name;
|
||||
const char *description;
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
static inline void counter_inc(struct counter *ctr)
|
||||
{
|
||||
ctr->value++;
|
||||
}
|
||||
|
||||
static inline unsigned long counter_get(struct counter *ctr)
|
||||
{
|
||||
return ctr->value;
|
||||
}
|
||||
|
||||
static inline void counter_reset(struct counter *ctr)
|
||||
{
|
||||
ctr->value = 0;
|
||||
}
|
||||
|
||||
struct counter *counter_alloc(const char *name);
|
||||
void counter_free(struct counter *ctr);
|
||||
|
||||
int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data);
|
||||
|
||||
#endif /* _STATISTICS_H */
|
|
@ -0,0 +1,192 @@
|
|||
#ifndef _TALLOC_H_
|
||||
#define _TALLOC_H_
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Samba temporary memory allocation functions
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004-2005
|
||||
Copyright (C) Stefan Metzmacher 2006
|
||||
|
||||
** NOTE! The following LGPL license applies to the talloc
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
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 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define HAVE_VA_COPY
|
||||
|
||||
/* this is only needed for compatibility with the old talloc */
|
||||
typedef void TALLOC_CTX;
|
||||
|
||||
/*
|
||||
this uses a little trick to allow __LINE__ to be stringified
|
||||
*/
|
||||
#ifndef __location__
|
||||
#define __TALLOC_STRING_LINE1__(s) #s
|
||||
#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
|
||||
#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
|
||||
#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
|
||||
#endif
|
||||
|
||||
#ifndef TALLOC_DEPRECATED
|
||||
#define TALLOC_DEPRECATED 0
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_ATTRIBUTE
|
||||
#if (__GNUC__ >= 3)
|
||||
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
|
||||
* the parameter containing the format, and a2 the index of the first
|
||||
* argument. Note that some gcc 2.x versions don't handle this
|
||||
* properly **/
|
||||
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
|
||||
#else
|
||||
#define PRINTF_ATTRIBUTE(a1, a2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* try to make talloc_set_destructor() and talloc_steal() type safe,
|
||||
if we have a recent gcc */
|
||||
#if (__GNUC__ >= 3)
|
||||
#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
|
||||
#define talloc_set_destructor(ptr, function) \
|
||||
do { \
|
||||
int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
|
||||
_talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
|
||||
} while(0)
|
||||
/* this extremely strange macro is to avoid some braindamaged warning
|
||||
stupidity in gcc 4.1.x */
|
||||
#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
|
||||
#else
|
||||
#define talloc_set_destructor(ptr, function) \
|
||||
_talloc_set_destructor((ptr), (int (*)(void *))(function))
|
||||
#define _TALLOC_TYPEOF(ptr) void *
|
||||
#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
|
||||
#endif
|
||||
|
||||
#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
|
||||
#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
|
||||
|
||||
/* useful macros for creating type checked pointers */
|
||||
#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
|
||||
#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
|
||||
#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
|
||||
|
||||
#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
|
||||
|
||||
#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
|
||||
#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
|
||||
|
||||
#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
|
||||
#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
|
||||
#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
|
||||
#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
|
||||
#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
|
||||
|
||||
#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
|
||||
#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
|
||||
|
||||
#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
|
||||
|
||||
#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
|
||||
#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
|
||||
#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
|
||||
|
||||
#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
|
||||
|
||||
#if TALLOC_DEPRECATED
|
||||
#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
|
||||
#define talloc_p(ctx, type) talloc(ctx, type)
|
||||
#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
|
||||
#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
|
||||
#define talloc_destroy(ctx) talloc_free(ctx)
|
||||
#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
|
||||
#endif
|
||||
|
||||
#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
|
||||
|
||||
/* The following definitions come from talloc.c */
|
||||
void *_talloc(const void *context, size_t size);
|
||||
void *talloc_pool(const void *context, size_t size);
|
||||
void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
|
||||
int talloc_increase_ref_count(const void *ptr);
|
||||
size_t talloc_reference_count(const void *ptr);
|
||||
void *_talloc_reference(const void *context, const void *ptr);
|
||||
int talloc_unlink(const void *context, void *ptr);
|
||||
const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
|
||||
void talloc_set_name_const(const void *ptr, const char *name);
|
||||
void *talloc_named(const void *context, size_t size,
|
||||
const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
|
||||
void *talloc_named_const(const void *context, size_t size, const char *name);
|
||||
const char *talloc_get_name(const void *ptr);
|
||||
void *talloc_check_name(const void *ptr, const char *name);
|
||||
void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
|
||||
void *talloc_parent(const void *ptr);
|
||||
const char *talloc_parent_name(const void *ptr);
|
||||
void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
|
||||
int talloc_free(void *ptr);
|
||||
void talloc_free_children(void *ptr);
|
||||
void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
|
||||
void *_talloc_steal(const void *new_ctx, const void *ptr);
|
||||
void *_talloc_move(const void *new_ctx, const void *pptr);
|
||||
size_t talloc_total_size(const void *ptr);
|
||||
size_t talloc_total_blocks(const void *ptr);
|
||||
void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
|
||||
void (*callback)(const void *ptr,
|
||||
int depth, int max_depth,
|
||||
int is_ref,
|
||||
void *private_data),
|
||||
void *private_data);
|
||||
void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
|
||||
void talloc_report_full(const void *ptr, FILE *f);
|
||||
void talloc_report(const void *ptr, FILE *f);
|
||||
void talloc_enable_null_tracking(void);
|
||||
void talloc_disable_null_tracking(void);
|
||||
void talloc_enable_leak_report(void);
|
||||
void talloc_enable_leak_report_full(void);
|
||||
void *_talloc_zero(const void *ctx, size_t size, const char *name);
|
||||
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
|
||||
void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
|
||||
void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
|
||||
void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
|
||||
void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
|
||||
void *talloc_autofree_context(void);
|
||||
size_t talloc_get_size(const void *ctx);
|
||||
void *talloc_find_parent_byname(const void *ctx, const char *name);
|
||||
void talloc_show_parents(const void *context, FILE *file);
|
||||
int talloc_is_parent(const void *context, const void *ptr);
|
||||
|
||||
char *talloc_strdup(const void *t, const char *p);
|
||||
char *talloc_strdup_append(char *s, const char *a);
|
||||
char *talloc_strdup_append_buffer(char *s, const char *a);
|
||||
|
||||
char *talloc_strndup(const void *t, const char *p, size_t n);
|
||||
char *talloc_strndup_append(char *s, const char *a, size_t n);
|
||||
char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
|
||||
|
||||
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
|
||||
char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
|
||||
char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
|
||||
|
||||
char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
|
||||
char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
|
||||
char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
|
||||
|
||||
void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "linuxlist.h"
|
||||
|
||||
/**
|
||||
* Timer management:
|
||||
* - Create a struct timer_list
|
||||
* - Fill out timeout and use add_timer or
|
||||
* use schedule_timer to schedule a timer in
|
||||
* x seconds and microseconds from now...
|
||||
* - Use del_timer to remove the timer
|
||||
*
|
||||
* Internally:
|
||||
* - We hook into select.c to give a timeval of the
|
||||
* nearest timer. On already passed timers we give
|
||||
* it a 0 to immediately fire after the select
|
||||
* - update_timers will call the callbacks and remove
|
||||
* the timers.
|
||||
*
|
||||
*/
|
||||
struct timer_list {
|
||||
struct llist_head entry;
|
||||
struct timeval timeout;
|
||||
unsigned int active : 1;
|
||||
unsigned int handled : 1;
|
||||
unsigned int in_list : 1;
|
||||
|
||||
void (*cb)(void*);
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* timer management
|
||||
*/
|
||||
void bsc_add_timer(struct timer_list *timer);
|
||||
void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds);
|
||||
void bsc_del_timer(struct timer_list *timer);
|
||||
int bsc_timer_pending(struct timer_list *timer);
|
||||
|
||||
|
||||
/**
|
||||
* internal timer list management
|
||||
*/
|
||||
struct timeval *bsc_nearest_timer();
|
||||
void bsc_prepare_timers();
|
||||
int bsc_update_timers();
|
||||
int bsc_timer_check(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,237 @@
|
|||
#ifndef _TLV_H
|
||||
#define _TLV_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocore/msgb.h>
|
||||
|
||||
/* Terminology / wording
|
||||
tag length value (in bits)
|
||||
|
||||
V - - 8
|
||||
LV - 8 N * 8
|
||||
TLV 8 8 N * 8
|
||||
TL16V 8 16 N * 8
|
||||
TLV16 8 8 N * 16
|
||||
TvLV 8 8/16 N * 8
|
||||
|
||||
*/
|
||||
|
||||
#define LV_GROSS_LEN(x) (x+1)
|
||||
#define TLV_GROSS_LEN(x) (x+2)
|
||||
#define TLV16_GROSS_LEN(x) ((2*x)+2)
|
||||
#define TL16V_GROSS_LEN(x) (x+3)
|
||||
#define L16TV_GROSS_LEN(x) (x+3)
|
||||
|
||||
#define TVLV_MAX_ONEBYTE 0x7f
|
||||
|
||||
static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
|
||||
{
|
||||
if (len <= TVLV_MAX_ONEBYTE)
|
||||
return TLV_GROSS_LEN(len);
|
||||
else
|
||||
return TL16V_GROSS_LEN(len);
|
||||
}
|
||||
|
||||
/* TLV generation */
|
||||
|
||||
static inline uint8_t *lv_put(uint8_t *buf, uint8_t len,
|
||||
const uint8_t *val)
|
||||
{
|
||||
*buf++ = len;
|
||||
memcpy(buf, val, len);
|
||||
return buf + len;
|
||||
}
|
||||
|
||||
static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
|
||||
const uint8_t *val)
|
||||
{
|
||||
*buf++ = tag;
|
||||
*buf++ = len;
|
||||
memcpy(buf, val, len);
|
||||
return buf + len;
|
||||
}
|
||||
|
||||
static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
|
||||
const uint16_t *val)
|
||||
{
|
||||
*buf++ = tag;
|
||||
*buf++ = len;
|
||||
memcpy(buf, val, len*2);
|
||||
return buf + len*2;
|
||||
}
|
||||
|
||||
static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
|
||||
const uint8_t *val)
|
||||
{
|
||||
*buf++ = tag;
|
||||
*buf++ = len >> 8;
|
||||
*buf++ = len & 0xff;
|
||||
memcpy(buf, val, len);
|
||||
return buf + len*2;
|
||||
}
|
||||
|
||||
static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
|
||||
const uint8_t *val)
|
||||
{
|
||||
uint8_t *ret;
|
||||
|
||||
if (len <= TVLV_MAX_ONEBYTE) {
|
||||
ret = tlv_put(buf, tag, len, val);
|
||||
buf[1] |= 0x80;
|
||||
} else
|
||||
ret = tl16v_put(buf, tag, len, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
|
||||
return tlv16_put(buf, tag, len, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len,
|
||||
const uint8_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
|
||||
return tl16v_put(buf, tag, len, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len,
|
||||
const uint8_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
|
||||
return tvlv_put(buf, tag, len, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
|
||||
const uint8_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len));
|
||||
|
||||
*buf++ = len >> 8;
|
||||
*buf++ = len & 0xff;
|
||||
*buf++ = tag;
|
||||
memcpy(buf, val, len);
|
||||
return buf + len;
|
||||
}
|
||||
|
||||
static inline uint8_t *v_put(uint8_t *buf, uint8_t val)
|
||||
{
|
||||
*buf++ = val;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
|
||||
uint8_t val)
|
||||
{
|
||||
*buf++ = tag;
|
||||
*buf++ = val;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* 'val' is still in host byte order! */
|
||||
static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
|
||||
uint16_t val)
|
||||
{
|
||||
*buf++ = tag;
|
||||
*buf++ = val >> 8;
|
||||
*buf++ = val & 0xff;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
|
||||
return lv_put(buf, len, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
|
||||
return tlv_put(buf, tag, len, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, 2);
|
||||
return tv_put(buf, tag, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, 1);
|
||||
return v_put(buf, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
|
||||
{
|
||||
uint8_t *buf = msgb_put(msg, 3);
|
||||
return tv16_put(buf, tag, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
|
||||
{
|
||||
uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
|
||||
return tlv_put(buf, tag, len, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
|
||||
{
|
||||
uint8_t *buf = msgb_push(msg, 2);
|
||||
return tv_put(buf, tag, val);
|
||||
}
|
||||
|
||||
static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
|
||||
{
|
||||
uint8_t *buf = msgb_push(msg, 3);
|
||||
return tv16_put(buf, tag, val);
|
||||
}
|
||||
|
||||
/* TLV parsing */
|
||||
|
||||
struct tlv_p_entry {
|
||||
uint16_t len;
|
||||
const uint8_t *val;
|
||||
};
|
||||
|
||||
enum tlv_type {
|
||||
TLV_TYPE_NONE,
|
||||
TLV_TYPE_FIXED,
|
||||
TLV_TYPE_T,
|
||||
TLV_TYPE_TV,
|
||||
TLV_TYPE_TLV,
|
||||
TLV_TYPE_TL16V,
|
||||
TLV_TYPE_TvLV,
|
||||
};
|
||||
|
||||
struct tlv_def {
|
||||
enum tlv_type type;
|
||||
uint8_t fixed_len;
|
||||
};
|
||||
|
||||
struct tlv_definition {
|
||||
struct tlv_def def[0xff];
|
||||
};
|
||||
|
||||
struct tlv_parsed {
|
||||
struct tlv_p_entry lv[0xff];
|
||||
};
|
||||
|
||||
extern struct tlv_definition tvlv_att_def;
|
||||
|
||||
int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
|
||||
const struct tlv_definition *def,
|
||||
const uint8_t *buf, int buf_len);
|
||||
int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
|
||||
const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2);
|
||||
/* take a master (src) tlvdev and fill up all empty slots in 'dst' */
|
||||
void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src);
|
||||
|
||||
#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
|
||||
#define TLVP_LEN(x, y) (x)->lv[y].len
|
||||
#define TLVP_VAL(x, y) (x)->lv[y].val
|
||||
|
||||
#endif /* _TLV_H */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef OSMOCORE_UTIL_H
|
||||
#define OSMOCORE_UTIL_H
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
/* bit vector utility routines */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocore/bitvec.h>
|
||||
|
||||
#define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit)
|
||||
|
||||
static inline unsigned int bytenum_from_bitnum(unsigned int bitnum)
|
||||
{
|
||||
unsigned int bytenum = bitnum / 8;
|
||||
|
||||
return bytenum;
|
||||
}
|
||||
|
||||
/* convert ZERO/ONE/L/H to a bitmask at given pos in a byte */
|
||||
static uint8_t bitval2mask(enum bit_value bit, uint8_t bitnum)
|
||||
{
|
||||
int bitval;
|
||||
|
||||
switch (bit) {
|
||||
case ZERO:
|
||||
bitval = (0 << bitnum);
|
||||
break;
|
||||
case ONE:
|
||||
bitval = (1 << bitnum);
|
||||
break;
|
||||
case L:
|
||||
bitval = ((0x2b ^ (0 << bitnum)) & (1 << bitnum));
|
||||
break;
|
||||
case H:
|
||||
bitval = ((0x2b ^ (1 << bitnum)) & (1 << bitnum));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return bitval;
|
||||
}
|
||||
|
||||
/* check if the bit is 0 or 1 for a given position inside a bitvec */
|
||||
enum bit_value bitvec_get_bit_pos(struct bitvec *bv, unsigned int bitnr)
|
||||
{
|
||||
unsigned int bytenum = bytenum_from_bitnum(bitnr);
|
||||
unsigned int bitnum = 7 - (bitnr % 8);
|
||||
uint8_t bitval;
|
||||
|
||||
if (bytenum >= bv->data_len)
|
||||
return -EINVAL;
|
||||
|
||||
bitval = bitval2mask(ONE, bitnum);
|
||||
|
||||
if (bv->data[bytenum] & bitval)
|
||||
return ONE;
|
||||
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
/* get the Nth set bit inside the bit vector */
|
||||
unsigned int bitvec_get_nth_set_bit(struct bitvec *bv, unsigned int n)
|
||||
{
|
||||
unsigned int i, k = 0;
|
||||
|
||||
for (i = 0; i < bv->data_len*8; i++) {
|
||||
if (bitvec_get_bit_pos(bv, i) == ONE) {
|
||||
k++;
|
||||
if (k == n)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the bit at a given position inside a bitvec */
|
||||
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
|
||||
enum bit_value bit)
|
||||
{
|
||||
unsigned int bytenum = bytenum_from_bitnum(bitnr);
|
||||
unsigned int bitnum = 7 - (bitnr % 8);
|
||||
uint8_t bitval;
|
||||
|
||||
if (bytenum >= bv->data_len)
|
||||
return -EINVAL;
|
||||
|
||||
/* first clear the bit */
|
||||
bitval = bitval2mask(ONE, bitnum);
|
||||
bv->data[bytenum] &= ~bitval;
|
||||
|
||||
/* then set it to desired value */
|
||||
bitval = bitval2mask(bit, bitnum);
|
||||
bv->data[bytenum] |= bitval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the next bit inside a bitvec */
|
||||
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = bitvec_set_bit_pos(bv, bv->cur_bit, bit);
|
||||
if (!rc)
|
||||
bv->cur_bit++;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* set multiple bits (based on array of bitvals) at current pos */
|
||||
int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
rc = bitvec_set_bit(bv, bits[i]);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set multiple bits (based on numeric value) at current pos */
|
||||
int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
int bit = 0;
|
||||
if (ui & (1 << (num_bits - i - 1)))
|
||||
bit = 1;
|
||||
rc = bitvec_set_bit(bv, bit);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pad all remaining bits up to num_bits */
|
||||
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = bv->cur_bit; i <= up_to_bit; i++)
|
||||
bitvec_set_bit(bv, L);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* COMP128 implementation
|
||||
*
|
||||
*
|
||||
* This code is inspired by original code from :
|
||||
* Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
|
||||
* and David Wagner <daw@cs.berkeley.edu>
|
||||
*
|
||||
* But it has been fully rewritten from various PDFs found online describing
|
||||
* the algorithm because the licence of the code referenced above was unclear.
|
||||
* A comment snippet from the original code is included below, it describes
|
||||
* where the doc came from and how the algorithm was reverse engineered.
|
||||
*
|
||||
*
|
||||
* (C) 2009 by Sylvain Munaut <tnt@246tNt.com>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* --- SNIP ---
|
||||
*
|
||||
* This code derived from a leaked document from the GSM standards.
|
||||
* Some missing pieces were filled in by reverse-engineering a working SIM.
|
||||
* We have verified that this is the correct COMP128 algorithm.
|
||||
*
|
||||
* The first page of the document identifies it as
|
||||
* _Technical Information: GSM System Security Study_.
|
||||
* 10-1617-01, 10th June 1988.
|
||||
* The bottom of the title page is marked
|
||||
* Racal Research Ltd.
|
||||
* Worton Drive, Worton Grange Industrial Estate,
|
||||
* Reading, Berks. RG2 0SB, England.
|
||||
* Telephone: Reading (0734) 868601 Telex: 847152
|
||||
* The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
|
||||
*
|
||||
* Note: There are three typos in the spec (discovered by
|
||||
* reverse-engineering).
|
||||
* First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
|
||||
* "z = (2 * x[m] + x[n]) mod 2^(9-j)".
|
||||
* Second, the "k" loop in the "Form bits from bytes" section is severely
|
||||
* botched: the k index should run only from 0 to 3, and clearly the range
|
||||
* on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
|
||||
* to be consistent with the subsequent section).
|
||||
* Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
|
||||
* claimed in the document. (And the document doesn't specify how Kc is
|
||||
* derived, but that was also easily discovered with reverse engineering.)
|
||||
* All of these typos have been corrected in the following code.
|
||||
*
|
||||
* --- /SNIP ---
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* The compression tables (just copied ...) */
|
||||
static const uint8_t table_0[512] = {
|
||||
102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188,
|
||||
109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161,
|
||||
252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70,
|
||||
67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116,
|
||||
247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225,
|
||||
182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48,
|
||||
149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176,
|
||||
250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121,
|
||||
61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196,
|
||||
56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231,
|
||||
174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255,
|
||||
239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82,
|
||||
104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5,
|
||||
57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226,
|
||||
184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23,
|
||||
80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119,
|
||||
177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246,
|
||||
213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108,
|
||||
37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59,
|
||||
26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207,
|
||||
194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215,
|
||||
243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245,
|
||||
90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137,
|
||||
27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32,
|
||||
103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172,
|
||||
197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210,
|
||||
165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125,
|
||||
54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192,
|
||||
170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198,
|
||||
254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147,
|
||||
218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154,
|
||||
159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253,
|
||||
}, table_1[256] = {
|
||||
19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43,
|
||||
27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
|
||||
35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6,
|
||||
53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20,
|
||||
90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78,
|
||||
76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
|
||||
57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67,
|
||||
12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
|
||||
95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29,
|
||||
82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114,
|
||||
82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
|
||||
113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73,
|
||||
118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83,
|
||||
104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126,
|
||||
31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
|
||||
101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35,
|
||||
}, table_2[128] = {
|
||||
52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
|
||||
37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
|
||||
55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
|
||||
62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
|
||||
48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
|
||||
29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
|
||||
20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
|
||||
31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7,
|
||||
}, table_3[64] = {
|
||||
1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
|
||||
28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
|
||||
20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
|
||||
17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19,
|
||||
}, table_4[32] = {
|
||||
15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
|
||||
10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12,
|
||||
};
|
||||
|
||||
static const uint8_t *_comp128_table[5] = { table_0, table_1, table_2, table_3, table_4 };
|
||||
|
||||
|
||||
static inline void
|
||||
_comp128_compression_round(uint8_t *x, int n, const uint8_t *tbl)
|
||||
{
|
||||
int i, j, m, a, b, y, z;
|
||||
m = 4 - n;
|
||||
for (i=0; i<(1<<n); i++)
|
||||
for (j=0; j<(1<<m); j++) {
|
||||
a = j + i * (2<<m);
|
||||
b = a + (1<<m);
|
||||
y = (x[a] + (x[b]<<1)) & ((32<<m)-1);
|
||||
z = ((x[a]<<1) + x[b]) & ((32<<m)-1);
|
||||
x[a] = tbl[y];
|
||||
x[b] = tbl[z];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_comp128_compression(uint8_t *x)
|
||||
{
|
||||
int n;
|
||||
for (n=0; n<5; n++)
|
||||
_comp128_compression_round(x, n, _comp128_table[n]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_comp128_bitsfrombytes(uint8_t *x, uint8_t *bits)
|
||||
{
|
||||
int i;
|
||||
memset(bits, 0x00, 128);
|
||||
for (i=0; i<128; i++)
|
||||
if (x[i>>2] & (1<<(3-(i&3))))
|
||||
bits[i] = 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_comp128_permutation(uint8_t *x, uint8_t *bits)
|
||||
{
|
||||
int i;
|
||||
memset(&x[16], 0x00, 16);
|
||||
for (i=0; i<128; i++)
|
||||
x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7));
|
||||
}
|
||||
|
||||
void
|
||||
comp128(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc)
|
||||
{
|
||||
int i;
|
||||
uint8_t x[32], bits[128];
|
||||
|
||||
/* x[16-31] = RAND */
|
||||
memcpy(&x[16], rand, 16);
|
||||
|
||||
/* Round 1-7 */
|
||||
for (i=0; i<7; i++) {
|
||||
/* x[0-15] = Ki */
|
||||
memcpy(x, ki, 16);
|
||||
|
||||
/* Compression */
|
||||
_comp128_compression(x);
|
||||
|
||||
/* FormBitFromBytes */
|
||||
_comp128_bitsfrombytes(x, bits);
|
||||
|
||||
/* Permutation */
|
||||
_comp128_permutation(x, bits);
|
||||
}
|
||||
|
||||
/* Round 8 (final) */
|
||||
/* x[0-15] = Ki */
|
||||
memcpy(x, ki, 16);
|
||||
|
||||
/* Compression */
|
||||
_comp128_compression(x);
|
||||
|
||||
/* Output stage */
|
||||
for (i=0; i<8; i+=2)
|
||||
sres[i>>1] = x[i]<<4 | x[i+1];
|
||||
|
||||
for (i=0; i<12; i+=2)
|
||||
kc[i>>1] = (x[i + 18] << 6) |
|
||||
(x[i + 19] << 2) |
|
||||
(x[i + 20] >> 2);
|
||||
|
||||
kc[6] = (x[30]<<6) | (x[31]<<2);
|
||||
kc[7] = 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
//#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/utils.h>
|
||||
#include <osmocore/gsm_utils.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
/* GSM 03.38 6.2.1 Charachter packing */
|
||||
int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length)
|
||||
{
|
||||
int i = 0;
|
||||
int l = 0;
|
||||
|
||||
/* FIXME: We need to account for user data headers here */
|
||||
i += l;
|
||||
for (; i < length; i ++)
|
||||
*(text ++) =
|
||||
((user_data[(i * 7 + 7) >> 3] <<
|
||||
(7 - ((i * 7 + 7) & 7))) |
|
||||
(user_data[(i * 7) >> 3] >>
|
||||
((i * 7) & 7))) & 0x7f;
|
||||
*text = '\0';
|
||||
|
||||
return i - l;
|
||||
}
|
||||
|
||||
|
||||
/* GSM 03.38 6.2.1 Charachter packing */
|
||||
int gsm_7bit_encode(uint8_t *result, const char *data)
|
||||
{
|
||||
int i,j = 0;
|
||||
unsigned char ch1, ch2;
|
||||
int shift = 0;
|
||||
|
||||
for ( i=0; i<strlen(data); i++ ) {
|
||||
|
||||
ch1 = data[i] & 0x7F;
|
||||
ch1 = ch1 >> shift;
|
||||
ch2 = data[(i+1)] & 0x7F;
|
||||
ch2 = ch2 << (7-shift);
|
||||
|
||||
ch1 = ch1 | ch2;
|
||||
|
||||
result[j++] = ch1;
|
||||
|
||||
shift++;
|
||||
|
||||
if ((shift == 7) && (i+1<strlen(data))) {
|
||||
shift = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* determine power control level for given dBm value, as indicated
|
||||
* by the tables in chapter 4.1.1 of GSM TS 05.05 */
|
||||
int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
|
||||
{
|
||||
switch (band) {
|
||||
case GSM_BAND_450:
|
||||
case GSM_BAND_480:
|
||||
case GSM_BAND_750:
|
||||
case GSM_BAND_900:
|
||||
case GSM_BAND_810:
|
||||
case GSM_BAND_850:
|
||||
if (dbm >= 39)
|
||||
return 0;
|
||||
else if (dbm < 5)
|
||||
return 19;
|
||||
else {
|
||||
/* we are guaranteed to have (5 <= dbm < 39) */
|
||||
return 2 + ((39 - dbm) / 2);
|
||||
}
|
||||
break;
|
||||
case GSM_BAND_1800:
|
||||
if (dbm >= 36)
|
||||
return 29;
|
||||
else if (dbm >= 34)
|
||||
return 30;
|
||||
else if (dbm >= 32)
|
||||
return 31;
|
||||
else if (dbm == 31)
|
||||
return 0;
|
||||
else {
|
||||
/* we are guaranteed to have (0 <= dbm < 31) */
|
||||
return (30 - dbm) / 2;
|
||||
}
|
||||
break;
|
||||
case GSM_BAND_1900:
|
||||
if (dbm >= 33)
|
||||
return 30;
|
||||
else if (dbm >= 32)
|
||||
return 31;
|
||||
else if (dbm == 31)
|
||||
return 0;
|
||||
else {
|
||||
/* we are guaranteed to have (0 <= dbm < 31) */
|
||||
return (30 - dbm) / 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
|
||||
{
|
||||
lvl &= 0x1f;
|
||||
|
||||
switch (band) {
|
||||
case GSM_BAND_450:
|
||||
case GSM_BAND_480:
|
||||
case GSM_BAND_750:
|
||||
case GSM_BAND_900:
|
||||
case GSM_BAND_810:
|
||||
case GSM_BAND_850:
|
||||
if (lvl < 2)
|
||||
return 39;
|
||||
else if (lvl < 20)
|
||||
return 39 - ((lvl - 2) * 2) ;
|
||||
else
|
||||
return 5;
|
||||
break;
|
||||
case GSM_BAND_1800:
|
||||
if (lvl < 16)
|
||||
return 30 - (lvl * 2);
|
||||
else if (lvl < 29)
|
||||
return 0;
|
||||
else
|
||||
return 36 - ((lvl - 29) * 2);
|
||||
break;
|
||||
case GSM_BAND_1900:
|
||||
if (lvl < 16)
|
||||
return 30 - (lvl * 2);
|
||||
else if (lvl < 30)
|
||||
return -EINVAL;
|
||||
else
|
||||
return 33 - (lvl - 30);
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* According to TS 08.05 Chapter 8.1.4 */
|
||||
int rxlev2dbm(uint8_t rxlev)
|
||||
{
|
||||
if (rxlev > 63)
|
||||
rxlev = 63;
|
||||
|
||||
return -110 + rxlev;
|
||||
}
|
||||
|
||||
/* According to TS 08.05 Chapter 8.1.4 */
|
||||
uint8_t dbm2rxlev(int dbm)
|
||||
{
|
||||
int rxlev = dbm + 110;
|
||||
|
||||
if (rxlev > 63)
|
||||
rxlev = 63;
|
||||
else if (rxlev < 0)
|
||||
rxlev = 0;
|
||||
|
||||
return rxlev;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
#include <execinfo.h>
|
||||
void generate_backtrace()
|
||||
{
|
||||
int i, nptrs;
|
||||
void *buffer[100];
|
||||
char **strings;
|
||||
|
||||
nptrs = backtrace(buffer, ARRAY_SIZE(buffer));
|
||||
printf("backtrace() returned %d addresses\n", nptrs);
|
||||
|
||||
strings = backtrace_symbols(buffer, nptrs);
|
||||
if (!strings)
|
||||
return;
|
||||
|
||||
for (i = 1; i < nptrs; i++)
|
||||
printf("%s\n", strings[i]);
|
||||
|
||||
free(strings);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <osmocore/msgb.h>
|
||||
//#include <openbsc/gsm_data.h>
|
||||
#include <osmocore/talloc.h>
|
||||
//#include <openbsc/debug.h>
|
||||
|
||||
void *tall_msgb_ctx;
|
||||
|
||||
struct msgb *msgb_alloc(uint16_t size, const char *name)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
msg = _talloc_zero(tall_msgb_ctx, sizeof(*msg) + size, name);
|
||||
|
||||
if (!msg) {
|
||||
//LOGP(DRSL, LOGL_FATAL, "unable to allocate msgb\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg->data_len = size;
|
||||
msg->len = 0;
|
||||
msg->data = msg->_data;
|
||||
|
||||
msg->head = msg->data;
|
||||
msg->data = msg->data;
|
||||
/* reset tail pointer */
|
||||
msg->tail = msg->data;
|
||||
//msg->end = msg->tail + size;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
void msgb_free(struct msgb *m)
|
||||
{
|
||||
talloc_free(m);
|
||||
}
|
||||
|
||||
void msgb_enqueue(struct llist_head *queue, struct msgb *msg)
|
||||
{
|
||||
llist_add_tail(&msg->list, queue);
|
||||
}
|
||||
|
||||
struct msgb *msgb_dequeue(struct llist_head *queue)
|
||||
{
|
||||
struct llist_head *lh;
|
||||
|
||||
if (llist_empty(queue))
|
||||
return NULL;
|
||||
|
||||
lh = queue->next;
|
||||
llist_del(lh);
|
||||
|
||||
return llist_entry(lh, struct msgb, list);
|
||||
}
|
||||
|
||||
void msgb_reset(struct msgb *msg)
|
||||
{
|
||||
msg->len = 0;
|
||||
msg->len = 0;
|
||||
msg->data = msg->_data;
|
||||
|
||||
msg->head = msg->data;
|
||||
msg->data = msg->data;
|
||||
/* reset tail pointer */
|
||||
msg->tail = msg->data;
|
||||
|
||||
/* reset pointers */
|
||||
msg->bts_link = NULL;
|
||||
msg->trx = NULL;
|
||||
msg->lchan = NULL;
|
||||
msg->l2h = NULL;
|
||||
msg->l3h = NULL;
|
||||
msg->smsh = NULL;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/* select filedescriptor handling, taken from:
|
||||
* userspace logging daemon for the iptables ULOG target
|
||||
* of the linux 2.4 netfilter subsystem.
|
||||
*
|
||||
* (C) 2000-2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <osmocore/select.h>
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <osmocore/timer.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
|
||||
static int maxfd = 0;
|
||||
static LLIST_HEAD(bsc_fds);
|
||||
static int unregistered_count;
|
||||
|
||||
int bsc_register_fd(struct bsc_fd *fd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
/* make FD nonblocking */
|
||||
flags = fcntl(fd->fd, F_GETFL);
|
||||
if (flags < 0)
|
||||
return flags;
|
||||
flags |= O_NONBLOCK;
|
||||
flags = fcntl(fd->fd, F_SETFL, flags);
|
||||
if (flags < 0)
|
||||
return flags;
|
||||
|
||||
/* Register FD */
|
||||
if (fd->fd > maxfd)
|
||||
maxfd = fd->fd;
|
||||
|
||||
llist_add_tail(&fd->list, &bsc_fds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bsc_unregister_fd(struct bsc_fd *fd)
|
||||
{
|
||||
unregistered_count++;
|
||||
llist_del(&fd->list);
|
||||
}
|
||||
|
||||
int bsc_select_main(int polling)
|
||||
{
|
||||
struct bsc_fd *ufd, *tmp;
|
||||
fd_set readset, writeset, exceptset;
|
||||
int work = 0, rc;
|
||||
struct timeval no_time = {0, 0};
|
||||
|
||||
FD_ZERO(&readset);
|
||||
FD_ZERO(&writeset);
|
||||
FD_ZERO(&exceptset);
|
||||
|
||||
/* prepare read and write fdsets */
|
||||
llist_for_each_entry(ufd, &bsc_fds, list) {
|
||||
if (ufd->when & BSC_FD_READ)
|
||||
FD_SET(ufd->fd, &readset);
|
||||
|
||||
if (ufd->when & BSC_FD_WRITE)
|
||||
FD_SET(ufd->fd, &writeset);
|
||||
|
||||
if (ufd->when & BSC_FD_EXCEPT)
|
||||
FD_SET(ufd->fd, &exceptset);
|
||||
}
|
||||
|
||||
bsc_timer_check();
|
||||
|
||||
if (!polling)
|
||||
bsc_prepare_timers();
|
||||
rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : bsc_nearest_timer());
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
|
||||
/* fire timers */
|
||||
bsc_update_timers();
|
||||
|
||||
/* call registered callback functions */
|
||||
restart:
|
||||
unregistered_count = 0;
|
||||
llist_for_each_entry_safe(ufd, tmp, &bsc_fds, list) {
|
||||
int flags = 0;
|
||||
|
||||
if (FD_ISSET(ufd->fd, &readset)) {
|
||||
flags |= BSC_FD_READ;
|
||||
FD_CLR(ufd->fd, &readset);
|
||||
}
|
||||
|
||||
if (FD_ISSET(ufd->fd, &writeset)) {
|
||||
flags |= BSC_FD_WRITE;
|
||||
FD_CLR(ufd->fd, &writeset);
|
||||
}
|
||||
|
||||
if (FD_ISSET(ufd->fd, &exceptset)) {
|
||||
flags |= BSC_FD_EXCEPT;
|
||||
FD_CLR(ufd->fd, &exceptset);
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
work = 1;
|
||||
ufd->cb(ufd, flags);
|
||||
}
|
||||
/* ugly, ugly hack. If more than one filedescriptors were
|
||||
* unregistered, they might have been consecutive and
|
||||
* llist_for_each_entry_safe() is no longer safe */
|
||||
if (unregistered_count > 1)
|
||||
goto restart;
|
||||
}
|
||||
return work;
|
||||
}
|
||||
|
||||
#endif /* _HAVE_SYS_SELECT_H */
|
|
@ -0,0 +1,84 @@
|
|||
/* Generic signalling/notification infrastructure */
|
||||
/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocore/signal.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
void *tall_sigh_ctx;
|
||||
static LLIST_HEAD(signal_handler_list);
|
||||
|
||||
struct signal_handler {
|
||||
struct llist_head entry;
|
||||
unsigned int subsys;
|
||||
signal_cbfn *cbfn;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data)
|
||||
{
|
||||
struct signal_handler *sig_data;
|
||||
|
||||
sig_data = talloc(tall_sigh_ctx, struct signal_handler);
|
||||
if (!sig_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(sig_data, 0, sizeof(*sig_data));
|
||||
|
||||
sig_data->subsys = subsys;
|
||||
sig_data->data = data;
|
||||
sig_data->cbfn = cbfn;
|
||||
|
||||
/* FIXME: check if we already have a handler for this subsys/cbfn/data */
|
||||
|
||||
llist_add_tail(&sig_data->entry, &signal_handler_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data)
|
||||
{
|
||||
struct signal_handler *handler;
|
||||
|
||||
llist_for_each_entry(handler, &signal_handler_list, entry) {
|
||||
if (handler->cbfn == cbfn && handler->data == data
|
||||
&& subsys == handler->subsys) {
|
||||
llist_del(&handler->entry);
|
||||
talloc_free(handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data)
|
||||
{
|
||||
struct signal_handler *handler;
|
||||
|
||||
llist_for_each_entry(handler, &signal_handler_list, entry) {
|
||||
if (handler->subsys != subsys)
|
||||
continue;
|
||||
(*handler->cbfn)(subsys, signal, handler->data, signal_data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* utility routines for keeping some statistics */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/statistics.h>
|
||||
|
||||
static LLIST_HEAD(counters);
|
||||
|
||||
void *tall_ctr_ctx;
|
||||
|
||||
struct counter *counter_alloc(const char *name)
|
||||
{
|
||||
struct counter *ctr = talloc_zero(tall_ctr_ctx, struct counter);
|
||||
|
||||
if (!ctr)
|
||||
return NULL;
|
||||
|
||||
ctr->name = name;
|
||||
llist_add_tail(&ctr->list, &counters);
|
||||
|
||||
return ctr;
|
||||
}
|
||||
|
||||
void counter_free(struct counter *ctr)
|
||||
{
|
||||
llist_del(&ctr->list);
|
||||
talloc_free(ctr);
|
||||
}
|
||||
|
||||
int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data)
|
||||
{
|
||||
struct counter *ctr;
|
||||
int rc = 0;
|
||||
|
||||
llist_for_each_entry(ctr, &counters, list) {
|
||||
rc = handle_counter(ctr, data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* (C) 2008,2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <osmocore/timer.h>
|
||||
|
||||
static LLIST_HEAD(timer_list);
|
||||
static struct timeval s_nearest_time;
|
||||
static struct timeval s_select_time;
|
||||
|
||||
#define MICRO_SECONDS 1000000LL
|
||||
|
||||
#define TIME_SMALLER(left, right) \
|
||||
(left.tv_sec*MICRO_SECONDS+left.tv_usec) <= (right.tv_sec*MICRO_SECONDS+right.tv_usec)
|
||||
|
||||
void bsc_add_timer(struct timer_list *timer)
|
||||
{
|
||||
struct timer_list *list_timer;
|
||||
|
||||
/* TODO: Optimize and remember the closest item... */
|
||||
timer->active = 1;
|
||||
|
||||
/* this might be called from within update_timers */
|
||||
llist_for_each_entry(list_timer, &timer_list, entry)
|
||||
if (timer == list_timer)
|
||||
return;
|
||||
|
||||
timer->in_list = 1;
|
||||
llist_add(&timer->entry, &timer_list);
|
||||
}
|
||||
|
||||
void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds)
|
||||
{
|
||||
struct timeval current_time;
|
||||
|
||||
gettimeofday(¤t_time, NULL);
|
||||
unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
|
||||
currentTime += seconds * MICRO_SECONDS + microseconds;
|
||||
timer->timeout.tv_sec = currentTime / MICRO_SECONDS;
|
||||
timer->timeout.tv_usec = currentTime % MICRO_SECONDS;
|
||||
bsc_add_timer(timer);
|
||||
}
|
||||
|
||||
void bsc_del_timer(struct timer_list *timer)
|
||||
{
|
||||
if (timer->in_list) {
|
||||
timer->active = 0;
|
||||
timer->in_list = 0;
|
||||
llist_del(&timer->entry);
|
||||
}
|
||||
}
|
||||
|
||||
int bsc_timer_pending(struct timer_list *timer)
|
||||
{
|
||||
return timer->active;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we have a nearest time return the delta between the current
|
||||
* time and the time of the nearest timer.
|
||||
* If the nearest timer timed out return NULL and then we will
|
||||
* dispatch everything after the select
|
||||
*/
|
||||
struct timeval *bsc_nearest_timer()
|
||||
{
|
||||
struct timeval current_time;
|
||||
|
||||
if (s_nearest_time.tv_sec == 0 && s_nearest_time.tv_usec == 0)
|
||||
return NULL;
|
||||
|
||||
if (gettimeofday(¤t_time, NULL) == -1)
|
||||
return NULL;
|
||||
|
||||
unsigned long long nearestTime = s_nearest_time.tv_sec * MICRO_SECONDS + s_nearest_time.tv_usec;
|
||||
unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
|
||||
|
||||
if (nearestTime < currentTime) {
|
||||
s_select_time.tv_sec = 0;
|
||||
s_select_time.tv_usec = 0;
|
||||
} else {
|
||||
s_select_time.tv_sec = (nearestTime - currentTime) / MICRO_SECONDS;
|
||||
s_select_time.tv_usec = (nearestTime - currentTime) % MICRO_SECONDS;
|
||||
}
|
||||
|
||||
return &s_select_time;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the nearest time and update s_nearest_time
|
||||
*/
|
||||
void bsc_prepare_timers()
|
||||
{
|
||||
struct timer_list *timer, *nearest_timer = NULL;
|
||||
llist_for_each_entry(timer, &timer_list, entry) {
|
||||
if (!nearest_timer || TIME_SMALLER(timer->timeout, nearest_timer->timeout)) {
|
||||
nearest_timer = timer;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearest_timer) {
|
||||
s_nearest_time = nearest_timer->timeout;
|
||||
} else {
|
||||
memset(&s_nearest_time, 0, sizeof(struct timeval));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fire all timers... and remove them
|
||||
*/
|
||||
int bsc_update_timers()
|
||||
{
|
||||
struct timeval current_time;
|
||||
struct timer_list *timer, *tmp;
|
||||
int work = 0;
|
||||
|
||||
gettimeofday(¤t_time, NULL);
|
||||
|
||||
/*
|
||||
* The callbacks might mess with our list and in this case
|
||||
* even llist_for_each_entry_safe is not safe to use. To allow
|
||||
* del_timer, add_timer, schedule_timer to be called from within
|
||||
* the callback we jump through some loops.
|
||||
*
|
||||
* First we set the handled flag of each active timer to zero,
|
||||
* then we iterate over the list and execute the callbacks. As the
|
||||
* list might have been changed (specially the next) from within
|
||||
* the callback we have to start over again. Once every callback
|
||||
* is dispatched we will remove the non-active from the list.
|
||||
*
|
||||
* TODO: If this is a performance issue we can poison a global
|
||||
* variable in add_timer and del_timer and only then restart.
|
||||
*/
|
||||
llist_for_each_entry(timer, &timer_list, entry) {
|
||||
timer->handled = 0;
|
||||
}
|
||||
|
||||
restart:
|
||||
llist_for_each_entry(timer, &timer_list, entry) {
|
||||
if (!timer->handled && TIME_SMALLER(timer->timeout, current_time)) {
|
||||
timer->handled = 1;
|
||||
timer->active = 0;
|
||||
(*timer->cb)(timer->data);
|
||||
work = 1;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
llist_for_each_entry_safe(timer, tmp, &timer_list, entry) {
|
||||
timer->handled = 0;
|
||||
if (!timer->active) {
|
||||
bsc_del_timer(timer);
|
||||
}
|
||||
}
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
int bsc_timer_check(void)
|
||||
{
|
||||
struct timer_list *timer;
|
||||
int i = 0;
|
||||
|
||||
llist_for_each_entry(timer, &timer_list, entry) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <osmocore/utils.h>
|
||||
#include <osmocore/tlv.h>
|
||||
|
||||
struct tlv_definition tvlv_att_def;
|
||||
|
||||
int tlv_dump(struct tlv_parsed *dec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= 0xff; i++) {
|
||||
if (!dec->lv[i].val)
|
||||
continue;
|
||||
printf("T=%02x L=%d\n", i, dec->lv[i].len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* o_tag: output: tag found
|
||||
* o_len: output: length of the data
|
||||
* o_val: output: pointer to the data
|
||||
* def: input: a structure defining the valid TLV tags / configurations
|
||||
* buf: input: the input data buffer to be parsed
|
||||
* buf_len: input: the length of the input data buffer
|
||||
*
|
||||
* Also, returns the number of bytes consumed by the TLV entry
|
||||
*/
|
||||
int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
|
||||
const struct tlv_definition *def,
|
||||
const uint8_t *buf, int buf_len)
|
||||
{
|
||||
uint8_t tag;
|
||||
int len;
|
||||
|
||||
tag = *buf;
|
||||
*o_tag = tag;
|
||||
|
||||
/* FIXME: use tables for knwon IEI */
|
||||
switch (def->def[tag].type) {
|
||||
case TLV_TYPE_T:
|
||||
/* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */
|
||||
*o_val = buf;
|
||||
*o_len = 0;
|
||||
len = 1;
|
||||
break;
|
||||
case TLV_TYPE_TV:
|
||||
*o_val = buf+1;
|
||||
*o_len = 1;
|
||||
len = 2;
|
||||
break;
|
||||
case TLV_TYPE_FIXED:
|
||||
*o_val = buf+1;
|
||||
*o_len = def->def[tag].fixed_len;
|
||||
len = def->def[tag].fixed_len + 1;
|
||||
break;
|
||||
case TLV_TYPE_TLV:
|
||||
/* GSM TS 04.07 11.2.4: Type 4 TLV */
|
||||
if (buf + 1 > buf + buf_len)
|
||||
return -1;
|
||||
*o_val = buf+2;
|
||||
*o_len = *(buf+1);
|
||||
len = *o_len + 2;
|
||||
if (len > buf_len)
|
||||
return -2;
|
||||
break;
|
||||
case TLV_TYPE_TvLV:
|
||||
if (*(buf+1) & 0x80) {
|
||||
/* like TLV, but without highest bit of len */
|
||||
if (buf + 1 > buf + buf_len)
|
||||
return -1;
|
||||
*o_val = buf+2;
|
||||
*o_len = *(buf+1) & 0x7f;
|
||||
len = *o_len + 2;
|
||||
if (len > buf_len)
|
||||
return -2;
|
||||
break;
|
||||
}
|
||||
/* like TL16V, fallthrough */
|
||||
case TLV_TYPE_TL16V:
|
||||
if (2 > buf_len)
|
||||
return -1;
|
||||
*o_val = buf+3;
|
||||
*o_len = *(buf+1) << 8 | *(buf+2);
|
||||
len = *o_len + 3;
|
||||
if (len > buf_len)
|
||||
return -2;
|
||||
break;
|
||||
default:
|
||||
return -3;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* dec: output: a caller-allocated pointer to a struct tlv_parsed,
|
||||
* def: input: a structure defining the valid TLV tags / configurations
|
||||
* buf: input: the input data buffer to be parsed
|
||||
* buf_len: input: the length of the input data buffer
|
||||
* lv_tag: input: an initial LV tag at the start of the buffer
|
||||
* lv_tag2: input: a second initial LV tag following lv_tag
|
||||
*/
|
||||
int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
|
||||
const uint8_t *buf, int buf_len, uint8_t lv_tag,
|
||||
uint8_t lv_tag2)
|
||||
{
|
||||
int ofs = 0, num_parsed = 0;
|
||||
uint16_t len;
|
||||
|
||||
memset(dec, 0, sizeof(*dec));
|
||||
|
||||
if (lv_tag) {
|
||||
if (ofs > buf_len)
|
||||
return -1;
|
||||
dec->lv[lv_tag].val = &buf[ofs+1];
|
||||
dec->lv[lv_tag].len = buf[ofs];
|
||||
len = dec->lv[lv_tag].len + 1;
|
||||
if (ofs + len > buf_len)
|
||||
return -2;
|
||||
num_parsed++;
|
||||
ofs += len;
|
||||
}
|
||||
if (lv_tag2) {
|
||||
if (ofs > buf_len)
|
||||
return -1;
|
||||
dec->lv[lv_tag2].val = &buf[ofs+1];
|
||||
dec->lv[lv_tag2].len = buf[ofs];
|
||||
len = dec->lv[lv_tag2].len + 1;
|
||||
if (ofs + len > buf_len)
|
||||
return -2;
|
||||
num_parsed++;
|
||||
ofs += len;
|
||||
}
|
||||
|
||||
while (ofs < buf_len) {
|
||||
int rv;
|
||||
uint8_t tag;
|
||||
const uint8_t *val;
|
||||
|
||||
rv = tlv_parse_one(&tag, &len, &val, def,
|
||||
&buf[ofs], buf_len-ofs);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
dec->lv[tag].val = val;
|
||||
dec->lv[tag].len = len;
|
||||
ofs += rv;
|
||||
num_parsed++;
|
||||
}
|
||||
//tlv_dump(dec);
|
||||
return num_parsed;
|
||||
}
|
||||
|
||||
/* take a master (src) tlvdev and fill up all empty slots in 'dst' */
|
||||
void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dst->def); i++) {
|
||||
if (src->def[i].type == TLV_TYPE_NONE)
|
||||
continue;
|
||||
if (dst->def[i].type == TLV_TYPE_NONE)
|
||||
dst->def[i] = src->def[i];
|
||||
}
|
||||
}
|
||||
|
||||
static __attribute__((constructor)) void on_dso_load_tlv(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++)
|
||||
tvlv_att_def.def[i].type = TLV_TYPE_TvLV;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <osmocore/msgb.h>
|
||||
#include <osmocore/gsm_utils.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
printf("SMS testing\n");
|
||||
struct msgb *msg;
|
||||
uint8_t *sms;
|
||||
uint8_t i;
|
||||
|
||||
/* test 7-bit coding/decoding */
|
||||
const char *input = "test text";
|
||||
uint8_t length;
|
||||
uint8_t coded[256];
|
||||
char result[256];
|
||||
|
||||
length = gsm_7bit_encode(coded, input);
|
||||
gsm_7bit_decode(result, coded, length);
|
||||
if (strcmp(result, input) != 0) {
|
||||
printf("7 Bit coding failed... life sucks\n");
|
||||
printf("Wanted: '%s' got '%s'\n", input, result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <osmocore/timer.h>
|
||||
#include <osmocore/select.h>
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
static void timer_fired(unsigned long data);
|
||||
|
||||
static struct timer_list timer_one = {
|
||||
.cb = timer_fired,
|
||||
.data = (void*)1,
|
||||
};
|
||||
|
||||
static struct timer_list timer_two = {
|
||||
.cb = timer_fired,
|
||||
.data = (void*)2,
|
||||
};
|
||||
|
||||
static struct timer_list timer_three = {
|
||||
.cb = timer_fired,
|
||||
.data = (void*)3,
|
||||
};
|
||||
|
||||
static void timer_fired(unsigned long data)
|
||||
{
|
||||
printf("Fired timer: %lu\n", data);
|
||||
|
||||
if (data == 1) {
|
||||
bsc_schedule_timer(&timer_one, 3, 0);
|
||||
bsc_del_timer(&timer_two);
|
||||
} else if (data == 2) {
|
||||
printf("Should not be fired... bug in del_timer\n");
|
||||
} else if (data == 3) {
|
||||
printf("Timer fired not registering again\n");
|
||||
} else {
|
||||
printf("wtf... wrong data\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
printf("Starting... timer\n");
|
||||
|
||||
bsc_schedule_timer(&timer_one, 3, 0);
|
||||
bsc_schedule_timer(&timer_two, 5, 0);
|
||||
bsc_schedule_timer(&timer_three, 4, 0);
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
while (1) {
|
||||
bsc_select_main(0);
|
||||
}
|
||||
#else
|
||||
printf("Select not supported on this platform!\n");
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue