summaryrefslogtreecommitdiffstats
path: root/example
diff options
context:
space:
mode:
Diffstat (limited to 'example')
-rw-r--r--example/.gitignore1
-rw-r--r--example/Makefile.in8
-rw-r--r--example/audio.c95
-rw-r--r--example/common.h23
-rw-r--r--example/event_ops.c115
-rwxr-xr-xexample/mmbin0 -> 39435 bytes
-rw-r--r--example/mm.c74
-rw-r--r--example/test.c294
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
new file mode 100755
index 0000000..bde150d
--- /dev/null
+++ b/example/mm
Binary files differ
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, &param);
+}
+
+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, &param);
+}
+
+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;
+}