diff options
Diffstat (limited to 'example')
-rw-r--r-- | example/.gitignore | 1 | ||||
-rw-r--r-- | example/Makefile.in | 8 | ||||
-rw-r--r-- | example/audio.c | 95 | ||||
-rw-r--r-- | example/common.h | 23 | ||||
-rw-r--r-- | example/event_ops.c | 115 | ||||
-rwxr-xr-x | example/mm | bin | 0 -> 39435 bytes | |||
-rw-r--r-- | example/mm.c | 74 | ||||
-rw-r--r-- | example/test.c | 294 |
8 files changed, 610 insertions, 0 deletions
diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/example/.gitignore @@ -0,0 +1 @@ +test diff --git a/example/Makefile.in b/example/Makefile.in new file mode 100644 index 0000000..da989a3 --- /dev/null +++ b/example/Makefile.in @@ -0,0 +1,8 @@ +LDFLAGS += -Lsrc -ldect +PROGRAMS += test + +test-destdir := usr/bin + +test-obj += event_ops.o +test-obj += audio.o +test-obj += test.o diff --git a/example/audio.c b/example/audio.c new file mode 100644 index 0000000..3dfe9cb --- /dev/null +++ b/example/audio.c @@ -0,0 +1,95 @@ +#include <SDL/SDL.h> +#include <SDL/SDL_audio.h> +#include "common.h" + +void dect_audio_queue(struct dect_audio_handle *ah, struct dect_msg_buf *mb) +{ + SDL_LockAudio(); + list_add_tail(&mb->list, &ah->queue); + SDL_UnlockAudio(); +} + +static void dect_decode_g721(struct g72x_state *codec, + int16_t *dst, const uint8_t *src, + unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len * 2; i += 2) { + dst[i + 0] = g721_decoder(src[i / 2] >> 4, + AUDIO_ENCODING_LINEAR, codec); + dst[i + 1] = g721_decoder(src[i / 2] & 0x0f, + AUDIO_ENCODING_LINEAR, codec); + } +} + +static void dect_audio_dequeue(void *data, uint8_t *stream, int len) +{ + struct dect_audio_handle *ah = data; + struct dect_msg_buf *mb; + int copy; + + len /= 4; + while (1) { + if (list_empty(&ah->queue)) + goto underrun; + mb = list_first_entry(&ah->queue, struct dect_msg_buf, list); + copy = mb->len; + if (copy > len) + copy = len; + + dect_decode_g721(&ah->codec, (int16_t *)stream, mb->data, copy); + dect_mbuf_pull(mb, copy); + if (mb->len == 0) { + list_del(&mb->list); + free(mb); + } + + len -= copy; + if (len == 0) + return; + stream += 4 * copy; + } + +underrun: + printf("audio underrun, missing %u bytes\n", len * 4); + memset(stream, 0, len * 4); +} + +struct dect_audio_handle *dect_audio_open(void) +{ + struct dect_audio_handle *ah; + SDL_AudioSpec spec = { + .freq = 8000, + .format = AUDIO_S16SYS, + .channels = 1, + .samples = 512, + .callback = dect_audio_dequeue, + }; + + ah = malloc(sizeof(*ah)); + if (ah == NULL) + goto err1; + init_list_head(&ah->queue); + g72x_init_state(&ah->codec); + + spec.userdata = ah; + if (SDL_OpenAudio(&spec, NULL) < 0) + goto err2; + SDL_PauseAudio(0); + + return ah; + +err2: + free(ah); +err1: + return NULL; +} + +static void __init dect_audio_init(void) +{ + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError()); + exit(1); + } +} diff --git a/example/common.h b/example/common.h new file mode 100644 index 0000000..cb73ec9 --- /dev/null +++ b/example/common.h @@ -0,0 +1,23 @@ +#ifndef _DECT_TEST_COMMON_H +#define _DECT_TEST_COMMON_H + +#include <libdect.h> +#include <utils.h> +#include <list.h> + +extern struct dect_handle *dh; +extern int dect_event_ops_init(struct dect_ops *ops); +extern void dect_event_loop(void); +extern void dect_event_ops_cleanup(void); + +#include "../src/ccitt-adpcm/g72x.h" + +struct dect_audio_handle { + struct g72x_state codec; + struct list_head queue; +}; + +extern struct dect_audio_handle *dect_audio_open(void); +extern void dect_audio_queue(struct dect_audio_handle *ah, struct dect_msg_buf *mb); + +#endif /* _DECT_TEST_COMMON_H */ diff --git a/example/event_ops.c b/example/event_ops.c new file mode 100644 index 0000000..2d1f586 --- /dev/null +++ b/example/event_ops.c @@ -0,0 +1,115 @@ +#include <stdlib.h> +#include <sys/types.h> +#include <sys/time.h> +#include <signal.h> +#include <event.h> + +#include <libdect.h> +#include "common.h" + +struct dect_handle *dh; + +static void event_callback(int fd, short mask, void *data) +{ + struct dect_fd *dfd = data; + uint32_t events; + + events = 0; + if (mask & EV_READ) + events |= DECT_FD_READ; + if (mask & EV_WRITE) + events |= DECT_FD_WRITE; + + dfd->callback(dh, dfd, events); +} + +static int register_fd(const struct dect_handle *dh, struct dect_fd *dfd, + uint32_t events) +{ + struct event *ev = (struct event *)dfd->priv; + unsigned short mask; + + mask = EV_PERSIST; + if (events & DECT_FD_READ) + mask |= EV_READ; + if (events & DECT_FD_WRITE) + mask |= EV_WRITE; + + event_set(ev, dfd->fd, mask, event_callback, dfd); + event_add(ev, NULL); + return 0; +} + +static void unregister_fd(const struct dect_handle *dh, struct dect_fd *dfd) +{ + struct event *ev = (struct event *)dfd->priv; + + event_del(ev); +} + +static void timer_expire(int fd, short mask, void *data) +{ + struct dect_timer *timer = data; + + timer->callback(dh, timer); +} + +static void start_timer(const struct dect_handle *dh, + struct dect_timer *timer, + const struct timeval *tv) +{ + struct event *ev = (struct event *)timer->priv; + + evtimer_set(ev, timer_expire, timer); + evtimer_add(ev, (struct timeval *)tv); +} + +static void stop_timer(const struct dect_handle *dh, struct dect_timer *timer) +{ + struct event *ev = (struct event *)timer->priv; + + evtimer_del(ev); +} + +static const struct dect_event_ops dect_event_ops = { + .fd_priv_size = sizeof(struct event), + .register_fd = register_fd, + .unregister_fd = unregister_fd, + .timer_priv_size = sizeof(struct event), + .start_timer = start_timer, + .stop_timer = stop_timer +}; + +static struct event_base *ev_base; +static struct event sig_event; +static bool sigint; + +static void sig_callback(int fd, short event, void *data) +{ + sigint = true; +} + +int dect_event_ops_init(struct dect_ops *ops) +{ + + ev_base = event_init(); + if (ev_base == NULL) + return -1; + ops->event_ops = &dect_event_ops; + + signal_set(&sig_event, SIGINT, sig_callback, NULL); + signal_add(&sig_event, NULL); + return 0; +} + +void dect_event_loop(void) +{ + while (!sigint) + event_loop(EVLOOP_ONCE); + signal_del(&sig_event); +} + +void dect_event_ops_cleanup(void) +{ + event_base_free(ev_base); +} diff --git a/example/mm b/example/mm Binary files differnew file mode 100755 index 0000000..bde150d --- /dev/null +++ b/example/mm diff --git a/example/mm.c b/example/mm.c new file mode 100644 index 0000000..af71011 --- /dev/null +++ b/example/mm.c @@ -0,0 +1,74 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dect/libdect.h> +#include "common.h" + +enum phones { PHONE1, PHONE2, PHONE3, }; +static const struct dect_ipui ipuis[] = { + [PHONE1] = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x08ae, + .psn = 0x83d1e, + }, + }, + [PHONE2] = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x08ae, + .psn = 0x8969f, + }, + }, + [PHONE3] = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x08ae, + .psn = 0x5b9a0, + }, + }, +}; + +static const struct dect_mm_ops mm_ops = { + .mm_access_rights_ind = 0, + .mm_access_rights_cfm = 0, +}; + +static int mm_access_rights_request(struct dect_handle *dh) +{ + struct dect_ie_portable_identity portable_identity; + struct dect_mm_access_rights_param param = { + .portable_identity = &portable_identity, + }; + + dect_ie_init(&portable_identity); + portable_identity.type = ID_TYPE_IPUI; + portable_identity.ipui = ipuis[PHONE1]; + + return dect_mm_access_rights_req(dh, ¶m); +} + +static struct dect_ops ops = { + .mm_ops = &mm_ops, +}; + +int main(int argc, char **argv) +{ + if (dect_event_ops_init(&ops) < 0) + exit(1); + + dh = dect_alloc_handle(&ops); + if (dh == NULL) + exit(1); + + if (dect_init(dh) < 0) + exit(1); + + if (mm_access_rights_request(dh) < 0) + exit(1); + + dect_event_loop(); + dect_close_handle(dh); + dect_event_ops_cleanup(); + return 0; +} diff --git a/example/test.c b/example/test.c new file mode 100644 index 0000000..02c5663 --- /dev/null +++ b/example/test.c @@ -0,0 +1,294 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <event.h> + +#include <dect/libdect.h> +#include <dect/terminal.h> +#include <dect/keypad.h> +#include "common.h" + +struct call { + struct dect_keypad_buffer *keybuf; + struct dect_audio_handle *audio; + struct event event; + enum { + BLINK0, + RING, + BLINK1, + SCROLLING, + } state; + uint8_t scroll_off; + uint8_t ring_pattern; +}; + +enum phones { PHONE1, PHONE2, PHONE3, }; +static const struct dect_ipui ipuis[] = { + [PHONE1] = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x08ae, + .psn = 0x83d1e, + }, + }, + [PHONE2] = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x08ae, + .psn = 0x8969f, + }, + }, + [PHONE3] = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x08ae, + .psn = 0x5b9a0, + }, + }, +}; + +static void dect_mncc_timer(int fd, short even, void *data); +static void dect_mncc_timer_schedule(struct dect_call *call) +{ + struct call *priv = dect_call_priv(call); + struct timeval tv = { .tv_sec = 1 }; + + evtimer_set(&priv->event, dect_mncc_timer, call); + evtimer_add(&priv->event, &tv); +} + +static void dect_mncc_timer(int fd, short even, void *data) +{ + struct dect_call *call = data; + struct dect_ie_display display; + struct dect_ie_signal signal; + struct dect_mncc_info_param info = { + //.signal = &signal, + .display = &display, + }; + static int code; + + init_list_head(&info.progress_indicator.list); + dect_ie_init(&signal); + signal.code = DECT_SIGNAL_ALERTING_BASE | (code % 10); + + dect_display_init(&display); + dect_display_append_char(&display, code++); + + dect_mncc_info_req(dh, call, &info); + dect_mncc_timer_schedule(call); +} + +static void dect_keypad_complete(struct dect_handle *dh, void *call, + struct dect_ie_keypad *keypad) +{ + printf("keypad complete: '%.*s'\n", keypad->len, keypad->info); +} + +static void dect_mncc_connect_ind(struct dect_handle *dh, struct dect_call *call, + const struct dect_mncc_connect_param *param) +{ + printf("MNCC_CONNECT-ind\n"); +} + +static void dect_mncc_setup_ind(struct dect_handle *dh, struct dect_call *call, + const struct dect_mncc_setup_param *setup) +{ + struct call *priv = dect_call_priv(call); + struct dect_ie_signal signal; + struct dect_mncc_connect_param connect = { + //.signal = &signal, + }; + + printf("MNCC_SETUP-ind\n"); + dect_ie_init(&signal); + signal.code = DECT_SIGNAL_DIAL_TONE_ON; + + priv->keybuf = dect_keypad_buffer_init(dh, 3, dect_keypad_complete, call); + priv->audio = dect_audio_open(); + + dect_mncc_connect_req(dh, call, &connect); +} + +static void dect_mncc_setup_ack_ind(struct dect_handle *dh, struct dect_call *call, + const struct dect_mncc_setup_ack_param *param) +{ + printf("MNCC_SETUP_ACK-ind\n"); +} + +static void dect_mncc_info_ind(struct dect_handle *dh, struct dect_call *call, + const struct dect_mncc_info_param *param) +{ + struct call *priv = dect_call_priv(call); + struct dect_ie_progress_indicator progress_indicator; + struct dect_ie_signal signal; + struct dect_mncc_info_param info = { + .signal = &signal, + }; + + printf("MNCC_INFO-ind\n"); + return; + dect_keypad_append(dh, priv->keybuf, param->keypad, + param->sending_complete); + + dect_ie_init(&signal); + signal.code = DECT_SIGNAL_DIAL_TONE_ON; + + dect_ie_init(&progress_indicator); + progress_indicator.location = DECT_LOCATION_PRIVATE_NETWORK_SERVING_LOCAL_USER; + progress_indicator.progress = DECT_PROGRESS_INBAND_INFORMATION_NOW_AVAILABLE; + + init_list_head(&info.progress_indicator.list); + list_add_tail(&progress_indicator.common.list, &info.progress_indicator.list); + + dect_mncc_info_req(dh, call, &info); +} + +static void dect_mncc_send_call_info(struct dect_call *call) +{ + struct call *priv = dect_call_priv(call); + struct dect_ie_display display; + struct dect_ie_signal signal; + struct dect_mncc_info_param info = { + .display = &display, + .signal = &signal, + }; + static const char *text = " kaber "; + + dect_display_init(&display); + dect_display_append_char(&display, DECT_C_CLEAR_DISPLAY); + dect_display_append_char(&display, '*'); + dect_display_append(&display, text + priv->scroll_off, + strlen(text) - priv->scroll_off); + dect_display_append(&display, text, priv->scroll_off); + dect_display_append_char(&display, '*'); + + dect_ie_init(&signal); + if (priv->state == RING) { + signal.code = DECT_SIGNAL_ALERTING_BASE | priv->ring_pattern; + priv->ring_pattern = (priv->ring_pattern + 1) % 8; + } else + signal.code = DECT_SIGNAL_ALERTING_BASE | DECT_RING_OFF; + + if (priv->state != SCROLLING) + priv->state++; + else { + priv->scroll_off = (priv->scroll_off + 1) % (strlen(text) + 1); + if (priv->scroll_off == 0) + priv->state = 0; + } + + dect_mncc_info_req(dh, call, &info); +} + +static void dect_mncc_info_timer(int fd, short even, void *data); +static void dect_mncc_info_timer_schedule(struct dect_call *call) +{ + struct call *priv = dect_call_priv(call); + struct timeval tv = { .tv_usec = 500000 }; + + evtimer_set(&priv->event, dect_mncc_info_timer, call); + evtimer_add(&priv->event, &tv); +} + +static void dect_mncc_info_timer(int fd, short even, void *data) +{ + struct dect_call *call = data; + + dect_mncc_send_call_info(call); + dect_mncc_info_timer_schedule(call); +} + +static void dect_mncc_alert_ind(struct dect_handle *dh, struct dect_call *call, + const struct dect_mncc_alert_param *param) +{ + printf("MNCC_ALERT-ind\n"); + dect_mncc_info_timer(0, 0, call); +} + +static void dect_mncc_reject_ind(struct dect_handle *dh, struct dect_call *call, + const struct dect_mncc_release_param *param) +{ + struct call *priv = dect_call_priv(call); + + printf("MNCC_REJECT-ind\n"); + event_del(&priv->event); +} + +static void dect_open_call(struct dect_handle *dh, const struct dect_ipui *ipui) +{ + struct dect_ie_basic_service basic_service; + struct dect_mncc_setup_param param = { + .basic_service = &basic_service, + }; + struct dect_call *call; + struct call *priv; + + call = dect_call_alloc(dh); + if (call == NULL) + return; + priv = dect_call_priv(call); + + dect_ie_init(&basic_service); + basic_service.class = DECT_CALL_CLASS_NORMAL; + basic_service.service = DECT_SERVICE_BASIC_SPEECH_DEFAULT; + + dect_mncc_setup_req(dh, call, ipui, ¶m); +} + +static void dect_dl_u_data_ind(struct dect_handle *dh, struct dect_call *call, + struct dect_msg_buf *mb) +{ + struct call *priv = dect_call_priv(call); + + dect_dl_u_data_req(dh, call, mb); + dect_audio_queue(priv->audio, mb); +} + +static const struct dect_cc_ops cc_ops = { + .priv_size = sizeof(struct call), + .mncc_connect_ind = dect_mncc_connect_ind, + .mncc_setup_ind = dect_mncc_setup_ind, + .mncc_setup_ack_ind = dect_mncc_setup_ack_ind, + .mncc_info_ind = dect_mncc_info_ind, + .mncc_alert_ind = dect_mncc_alert_ind, + .mncc_reject_ind = dect_mncc_reject_ind, + .dl_u_data_ind = dect_dl_u_data_ind, +}; + +static const struct dect_mm_ops mm_ops = { + .mm_access_rights_ind = 0, + .mm_access_rights_cfm = 0, +}; + +static struct dect_ops ops = { + .cc_ops = &cc_ops, + .mm_ops = &mm_ops, +}; + +int main(int argc, char **argv) +{ + if (dect_event_ops_init(&ops) < 0) + exit(1); + + dh = dect_alloc_handle(&ops); + if (dh == NULL) + exit(1); + + if (dect_init(dh) < 0) + exit(1); + +#if 0 + //dect_lce_group_ring(dh, 0xf); + dect_open_call(dh, &ipuis[PHONE1]); + dect_open_call(dh, &ipuis[PHONE3]); +#else + dect_open_call(dh, &ipuis[PHONE2]); +#endif + dect_event_loop(); + dect_close_handle(dh); + dect_event_ops_cleanup(); + return 0; +} |