r40 - in trunk/src/target: . gsm gsm/include gsm/include/common gsm/include/gsmd gsm/include/libgsmd gsm/logs gsm/src gsm/src/gsmd gsm/src/libgsmd

laforge at gta01.hmw-consulting.de laforge at gta01.hmw-consulting.de
Sat Sep 2 12:32:19 CEST 2006


Author: laforge
Date: 2006-09-02 10:32:06 +0000 (Sat, 02 Sep 2006)
New Revision: 40

Added:
   trunk/src/target/gsm/
   trunk/src/target/gsm/README.txt
   trunk/src/target/gsm/include/
   trunk/src/target/gsm/include/common/
   trunk/src/target/gsm/include/common/gsmd_proto.h
   trunk/src/target/gsm/include/common/linux_list.h
   trunk/src/target/gsm/include/gsmd/
   trunk/src/target/gsm/include/gsmd/event.h
   trunk/src/target/gsm/include/gsmd/gsmd.h
   trunk/src/target/gsm/include/gsmd/usock.h
   trunk/src/target/gsm/include/libgsmd/
   trunk/src/target/gsm/include/libgsmd/event.h
   trunk/src/target/gsm/include/libgsmd/handset.h
   trunk/src/target/gsm/include/libgsmd/libgsmd.h
   trunk/src/target/gsm/include/libgsmd/misc.h
   trunk/src/target/gsm/include/libgsmd/phonebook.h
   trunk/src/target/gsm/include/libgsmd/voicecall.h
   trunk/src/target/gsm/logs/
   trunk/src/target/gsm/logs/screenlog.0
   trunk/src/target/gsm/src/
   trunk/src/target/gsm/src/gsmd/
   trunk/src/target/gsm/src/gsmd/.gpsd.h.swp
   trunk/src/target/gsm/src/gsmd/Makefile
   trunk/src/target/gsm/src/gsmd/atcmd.c
   trunk/src/target/gsm/src/gsmd/atcmd.h
   trunk/src/target/gsm/src/gsmd/gsmd.c
   trunk/src/target/gsm/src/gsmd/gsmd.h
   trunk/src/target/gsm/src/gsmd/gsmd_event.h
   trunk/src/target/gsm/src/gsmd/select.c
   trunk/src/target/gsm/src/gsmd/select.h
   trunk/src/target/gsm/src/gsmd/unsolicited.c
   trunk/src/target/gsm/src/gsmd/unsolicited.h
   trunk/src/target/gsm/src/gsmd/usock.c
   trunk/src/target/gsm/src/gsmd/usock.h
   trunk/src/target/gsm/src/gsmd/vendor_ti.c
   trunk/src/target/gsm/src/gsmd/vendorplugin.h
   trunk/src/target/gsm/src/libgsmd/
   trunk/src/target/gsm/src/libgsmd/lgsm_internals.h
   trunk/src/target/gsm/src/libgsmd/libgsmd.c
   trunk/src/target/gsm/src/libgsmd/libgsmd_input.c
   trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c
Log:
first compiling (unfinished, not-working) version of userspace gsm infrastructure


Added: trunk/src/target/gsm/README.txt
===================================================================
--- trunk/src/target/gsm/README.txt	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/README.txt	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,54 @@
+
+
+1. GSMD api towards libgsmd 
+	- provides api for other processes to interact with GSM subsystem
+
+2. GSMD api towards vendor-specific plugins
+	- implement vendor-specific AT commands
+
+3. libgsmd api towards applications
+	- wraps GSMD-libgsmd api into C functions that can be used by applications
+
+
+
+code flow in gsmd:
+
+- select loop detects data has arrived on user socket
+	- gsmd_usock_user_cb()
+		- if this is atcmd passthrough, 
+			- alloc + fill in gsmd_atcmd
+			- atcmd_submit()
+				- append it to pending_atcmds
+				- mark interest of writing to UART
+		- if this is not passthrough
+			- do whatever handling, including enqueueing of atcmds
+- select loop detects UART is marked writable
+	- atcmd_select_cb()
+		- iterate over list of pending_atcmds()
+			- write a particular atcmd to UART
+			- move atcmd to busy_atcmds
+- select loop detects UART is marked readable
+	- atcmd_select_cb()
+		- read up to 1024 bytes into buffer
+		- llparse_string()
+			- llparse_byte()
+				- llparse_append()
+			- llp->cb == ml_parse()
+				- if this is not unsolicited
+					- call cmd->cb() 
+						- alloc + fill ucmd reply
+						- add to finished_ucmds
+						- mark user sock writable
+					- unlink + free atcmd
+				- if this is unsolicited
+					- unsolicited_parse()
+						- usock_evt_send()
+							- alloc + fill ucmd reply
+							- add to finished_ucmds
+							- mark user sock writable
+- select loop detects user sock writeability
+	- gsmd_usock_user_cb()
+		- iterate over finished_ucmds
+			- write ucmd
+			- unlink + free ucmd
+

Added: trunk/src/target/gsm/include/common/gsmd_proto.h
===================================================================
--- trunk/src/target/gsm/include/common/gsmd_proto.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/common/gsmd_proto.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,9 @@
+#ifndef _GSMD_PROTO_H
+#define _GSMD_PROTO_H
+
+/* this header file describes the protocol between gsmd and libgsmd 
+ * (C) 2006 by Harald Welte <hwelte at hmw-consulting.de> */
+
+
+
+#endif /* _GSMD_PROTO_H */

Added: trunk/src/target/gsm/include/common/linux_list.h
===================================================================
--- trunk/src/target/gsm/include/common/linux_list.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/common/linux_list.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,364 @@
+#ifndef _LINUX_LLIST_H
+#define _LINUX_LLIST_H
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x)	(sizeof(x) / sizeof((x)[0]))
+#endif
+
+#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 = (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 = LLIST_POISON1;
+	entry->prev = 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

Added: trunk/src/target/gsm/include/gsmd/event.h
===================================================================
--- trunk/src/target/gsm/include/gsmd/event.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/gsmd/event.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,52 @@
+#ifndef _GSMD_EVENT_H
+#define _GSMD_EVENT_H
+
+enum gsmd_events {
+	GSMD_EVT_NONE		= 0,
+	GSMD_EVT_IN_CALL	= 1,	/* Incoming call */
+	GSMD_EVT_IN_SMS		= 2,	/* Incoming SMS */
+	GSMD_EVT_IN_GPRS	= 3,	/* Network initiated GPRS */
+	GSMD_EVT_IN_CLIP	= 4,	/* Incoming CLIP */
+	GSMD_EVT_NETREG		= 5,	/* Network (un)registration event */
+	GSMD_EVT_SIGNAL		= 6,	/* Signal quality event */
+	GSMD_EVT_PIN		= 7, 	/* Modem is waiting for some PIN/PUK */
+	GSMD_EVT_OUT_STATUS	= 8,	/* Outgoing call status */
+	GSMD_EVT_OUT_COLP	= 9,	/* Outgoing COLP */
+	GSMD_EVT_CALL_WAIT	= 10,	/* Call Waiting */
+};
+
+/* Chapter 8.3 */
+enum gsmd_pin_type {			/* waiting for ... */
+	GSMD_PIN_NONE		= 0,	/* not for any PIN */
+	GSMD_PIN_SIM_PIN	= 1,	/* SIM PIN */
+	GSMD_PIN_SIM_PUK	= 2,	/* SIM PUK */
+	GSMD_PIN_PH_SIM_PIN	= 3,	/* phone-to-SIM passowrd */
+	GSMD_PIN_PH_FSIM_PIN	= 4,	/* phone-to-very-first SIM password */
+	GSMD_PIN_PH_FSIM_PUK	= 5,	/* phone-to-very-first SIM PUK password */
+	GSMD_PIN_SIM_PIN2	= 6,	/* SIM PIN2 */
+	GSMD_PIN_SIM_PUK2	= 7,	/* SIM PUK2 */
+	GSMD_PIN_PH_NET_PIN	= 8,	/* netwokr personalisation password */
+	GSMD_PIN_PH_NET_PUK	= 9,	/* network personalisation PUK */
+	GSMD_PIN_PH_NETSUB_PIN	= 10, 	/* network subset personalisation PIN */
+	GSMD_PIN_PH_NETSUB_PUK	= 11,	/* network subset personalisation PUK */
+	GSMD_PIN_PH_SP_PIN	= 12,	/* service provider personalisation PIN */
+	GSMD_PIN_PH_SP_PUK	= 13,	/* service provider personalisation PUK */
+	GSMD_PIN_PH_CORP_PIN	= 14,	/* corporate personalisation PIN */
+	GSMD_PIN_PH_CORP_PUK	= 15,	/* corporate personalisation PUK */
+};
+
+enum gsmd_call_type {
+	GSMD_CALL_NONE		= 0,
+	GSMD_CALL_UNSPEC	= 1,
+	GSMD_CALL_VOICE		= 2,
+	GSMD_CALL_FAX		= 4,
+	GSMD_CALL_DATA_SYNC	= 5,
+	GSMD_CALL_DATA_REL_ASYNC= 6,
+	GSMD_CALL_DATA_REL_SYNC	= 7,
+};
+
+enum gsmd_netreg_state {
+	GSMD_NETREG_NONE	= 0,
+};
+
+#endif

Added: trunk/src/target/gsm/include/gsmd/gsmd.h
===================================================================
--- trunk/src/target/gsm/include/gsmd/gsmd.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/gsmd/gsmd.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,4 @@
+#ifndef _GSMD_H
+#define _GSMD_H
+
+#endif /* _GSMD_H */

Added: trunk/src/target/gsm/include/gsmd/usock.h
===================================================================
--- trunk/src/target/gsm/include/gsmd/usock.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/gsmd/usock.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,83 @@
+#ifndef _GSMD_USOCK_H
+#define _GSMD_USOCK_H
+
+#include <gsmd/event.h>
+
+#define GSMD_UNIX_SOCKET "\0gsmd"
+#define GSMD_UNIX_SOCKET_TYPE SOCK_SEQPACKET
+
+#define GSMD_PROTO_VERSION	1
+
+enum gsmd_prot_cmd {
+	GSMD_PCMD_NONE,
+	GSMD_PCMD_EVT_SUBSCRIPTIONS,		/* alter event subscriptions */
+	GSMD_PCMD_PASSTHROUGH,			/* transparent atcmd passthrough */
+};
+
+enum gsmd_pcmd_result {
+	GSMD_PCMD_OK		= 0,
+	GSMD_PCMD_ERR_UNSPEC	= 0xff,
+};
+
+struct gsmd_prot_hdr {
+	u_int16_t cmd;
+	u_int8_t result;
+	u_int8_t version;
+} __attribute__((packed));
+
+
+enum gsmd_msg_type {
+	GSMD_MSG_NONE		= 0,
+	GSMD_MSG_EVENT		= 1,
+	GSMD_MSG_PASSTHROUGH	= 2,
+};
+
+enum gsmd_passthrough_type {
+	GSMD_PASSTHROUGH_NONE	= 0,
+	GSMD_PASSTHROUGH_REQ	= 1,
+	GSMD_PASSTHROUGH_RESP	= 2,
+};
+
+/* Length from 3GPP TS 04.08, Clause 10.5.4.7 */
+
+#define GSMD_ADDR_MAXLEN	13
+struct gsmd_addr {
+	u_int8_t type;
+	char number[GSMD_ADDR_MAXLEN+1];
+};
+
+struct gsmd_evt_auxdata {
+	union {
+		struct {
+			enum gsmd_call_type type;
+		} call;
+		struct {
+			struct gsmd_addr addr;
+		} clip;
+		struct {
+			struct gsmd_addr addr;
+		} colp;
+		struct {
+			/* TBD */
+			struct gsmd_addr addr;
+		} sms;
+		struct {
+			enum gsmd_pin_type type;
+		} pin;
+		struct {
+			enum gsmd_netreg_state state;
+			u_int16_t lac;
+			u_int16_t ci;
+		} netreg;
+	} u;
+};
+
+struct gsmd_msg_hdr {
+	u_int8_t version;
+	u_int8_t msg_type;
+	u_int8_t msg_subtype;
+	u_int8_t len;
+} __attribute__((packed));
+
+
+#endif

Added: trunk/src/target/gsm/include/libgsmd/event.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/event.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/libgsmd/event.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,14 @@
+#ifndef _LIBGSMD_EVENT_H
+#define _LIBGSMD_EVENT_H
+
+#include <gsmd/event.h>
+
+/* Prototype of libgsmd callback handler function */
+typedef int evt_cb_func(struct lgsm_handle *lh, enum gsmd_events evt, 
+			void *user);
+
+/* Register an event callback handler with libgsmd */
+extern int lgsm_register_evt_cb(struct lgsm_handle *lh, 
+				evt_cb_func *cb, void *user);
+
+#endif

Added: trunk/src/target/gsm/include/libgsmd/handset.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/handset.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/libgsmd/handset.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,15 @@
+#ifndef _LIBGSMD_HANDSET_H
+#define _LIBGSMD_HANDSET_H
+
+#include <libgsmd/libgsmd.h>
+/* Set speaker level (Chapter 8.23) */
+extern int lgsm_set_spkr_level(struct lgsm_handle *lh,
+			       u_int32_t level);
+
+/* Mute call during voice call */
+extern int lgsm_mute_set(struct lgsm_handle *lh, u_int8_t on);
+
+/* Get information on whether voice call is muted or not */
+extern int lgsm_mute_get(struct lgsm_handle *lh, u_int8_t *on);
+
+#endif

Added: trunk/src/target/gsm/include/libgsmd/libgsmd.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/libgsmd.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/libgsmd/libgsmd.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,50 @@
+#ifndef _LIBGSMD_H
+#define _LIBGSMD_H
+
+/* libgsmd.h - Library API for gsmd, the GSM Daemon
+ * (C) 2006 by Harald Welte <hwelte at hmw-consulting.de>
+ * Development funded by First International Computers, Inc.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+
+/* Generic Information
+ *
+ * Return value:
+ * 	< 0	Error, see libgsmd/errno.h and errno.h
+ * 	= 0	Success
+ * 	> 0	Success, number of information elements returned
+ *
+ * Allocation:
+ * 	All data structures are caller-allocated.  The only exception
+ * 	is struct lgsm_handle which is allocatedi in lgsm_init() and 
+ * 	free'd in lgsm_exit()
+ *
+ * References:
+ * 	Recefences to "Chapter X" are referring to 3GPP TS 07.07 version 7.8.0
+ */
+
+/* Opaque data structure, content only known to libgsm implementation */
+struct lgsm_handle;
+
+/* initialize usage of libgsmd, obtain handle for othe API calls */
+extern struct lgsm_handle *lgsm_init(void);
+
+/* Terminate usage of libgsmd */
+extern int lgsm_exit(struct lgsm_handle *lh); 
+
+/* Refer to GSM 04.08 [8] subclause 10.5.4.7 */
+enum lgsm_addr_type {
+	LGSM_ATYPE_ISDN_UNKN		= 161,
+	LGSM_ATYPE_ISDN_INTL		= ,
+	LGSM_ATYPE_ISDN_NATIONAL	= ,
+};
+
+#define LGSM_ADDR_MAXLEN	31
+struct lgsm_addr {
+	char addr[LGSM_ADDR_MAXLEN+1];
+	enum lgsm_addr_type tyoe;
+};
+
+#endif

Added: trunk/src/target/gsm/include/libgsmd/misc.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/misc.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/libgsmd/misc.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,72 @@
+#ifndef _LIBGSMD_H
+#define _LIBGSMD_H
+
+/* libgsmd.h - Library API for gsmd, the GSM Daemon
+ * (C) 2006 by Harald Welte <hwelte at hmw-consulting.de>
+ * Development funded by First International Computers, Inc.
+ */
+
+#include <libgsmd/libgsmd.h>
+
+enum lgsm_netreg_state {
+	LGSM_NETREG_ST_NOTREG		= 0,
+	LGSM_NETREG_ST_REG_HOME		= 1,
+	LGSM_NETREG_ST_NOTREG_SEARCH	= 2,
+	LGSM_NETREG_ST_DENIED		= 3,
+	LGSM_NETREG_ST_UNKNOWN		= 4,
+	LGSM_NETREG_ST_REG_ROAMING	= 5,
+};
+
+/* Get the current network registration status */
+extern int lgsm_get_netreg_state(struct lgsm_handle *lh,
+				 enum lgsm_netreg_state *state);
+
+enum lgsm_info_type {
+	LGSM_INFO_TYPE_NONE		= 0,
+	LGSM_INFO_TYPE_MANUF		= 1,
+	LGSM_INFO_TYPE_MODEL		= 2,
+	LGSM_INFO_TYPE_REVISION		= 3,
+	LGSM_INFO_TYPE_SERIAL		= 4,
+	LGSM_INFO_TYPE_IMSI		= 5,
+};
+
+/* Get some information about the handset */
+extern int lgsm_get_info(struct lgsm_handle *lh,
+			 enum lgsm_info_type type,
+			 char *ret_string, u_int16_t len);
+
+/* Authenticate to SIM Card using specified null-terminated pin */
+extern int lgsm_pin_auth(struct lgsm_handle *lh, const char *pin);
+
+
+/* General Commands */
+
+/* Get Signal Strehngth (Chapter 8.5) */
+extern int lgsm_get_signal_quality(struct lgsm_handle *h,
+				   unsigned int *rssi);
+
+/* Set voice mail number */
+extern int lgsm_voicemail_set(struct lgsm_handle *lh,
+			      struct lgsm_addr *addr);
+
+/* Get currently configured voice mail number */
+extern int lgsm_voicemail_get(struct lgsm_handle *lh,
+			      struct lgsm_addr *addr);
+
+/* Operator Selection, Network Registration */
+/* TBD */
+
+
+/* CLIP, CLIR, COLP, Call Forwarding, Call Waiting, Call Deflecting */
+/* TBD */
+
+
+/* SMS related functions */
+/* TBD */
+
+
+/* GPRS related functions */
+/* TBD */
+
+
+#endif

Added: trunk/src/target/gsm/include/libgsmd/phonebook.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/phonebook.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/libgsmd/phonebook.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,51 @@
+#ifndef _LIBGSMD_PBOOK_H
+#define _LIBGSMD_PBOOK_H
+
+#include <libgsmd/libgsmd.h>
+
+/* Phonebook */
+
+/* Chapter 8.11 */
+enum lgsm_pbook_type {
+	LGSM_PB_ME_DIALLED		= 1,
+	LGSM_PB_SIM_EMERGENCY		= 2,
+	LGSM_PB_SIM_FIXDIAL		= 3,
+	LGSM_PB_SIM_DIALLED		= 4,
+	LGSM_PB_ME_MISSED		= 5,
+	LGSM_PB_ME_PHONEBOOK		= 6,
+	LGSM_PB_COMB_PHONEBOOK		= 7,
+	LGSM_PB_SIM_OWN_NUMBERS		= 8,
+	LGSM_PB_ME_RECEIVED		= 9,
+	LGSM_PB_SIM_PHONEBOOK		= 10,
+	LGSM_PB_TA_PHONEBOOK		= 11,
+};
+
+/* Get a bitmask of supported phonebook types */
+extern int lgsm_pb_get_types(struct lgsm_handle *lh, u_int32 *typemask);
+
+/* Get a range of supported indexes in given phonebook type, Chapter 8.12 */
+extern int lgsm_pb_get_range(struct lgsm_handle *lh,
+			     enum lgsm_pbook_type type,
+			     u_int32_t *from, u_int32_t *to,
+			     u_int32_t *nlength, *u_int32_t tlength);
+
+#define LGSM_PB_TEXT_MAXLEN	31
+
+struct lgsm_pb_entry {
+	struct lgsm_pb_entry	*next;
+	enum lgsm_pbook_type 	type;
+	u_int32_t 		index;
+	char 			text[LGSM_PB_TEXT_MAXLEN+1];
+};
+
+/* Get a specific phonebook entry  and store it to 'pb'
+ * pb' is caller-allocated */
+extern int lgsm_pb_get_entry(struct lgsm_handle *lh,
+			     struct lgsm_pb_entry *pb);
+
+/* Store a specific phonebook entry 'pb' into phone */
+extern int lgsm_pb_set_entry(struct lgsm_handle *lh,
+			     struct lgsm_pb_entry *pb);
+
+
+#endif

Added: trunk/src/target/gsm/include/libgsmd/voicecall.h
===================================================================
--- trunk/src/target/gsm/include/libgsmd/voicecall.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/include/libgsmd/voicecall.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,18 @@
+#ifndef _LIBGSMD_VCALL_H
+#define _LIBGSMD_VCALL_H
+
+#include <libgsmd/libgsmd.h>
+
+/* Voice Calls */
+
+/* Initiate an outgoing voice call */
+extern int lgsm_voice_out_init(struct lgsm_handle *lh, 
+			       const struct lgsm_addr *number);
+
+/* Accept incoming voice call */
+extern int lgsm_voice_in_accept(struct lgsm_handle *lh);
+
+/* Terminate outgoing (or incoming) voice call */
+extern int lgsm_voice_hangup(struct lgsm_handle *lh);
+
+#endif

Added: trunk/src/target/gsm/logs/screenlog.0
===================================================================
--- trunk/src/target/gsm/logs/screenlog.0	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/logs/screenlog.0	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,500 @@
+ccu -l /dev/ttU yUSB0 -s 15200
+cu: Unsupported baud rate 15200
+%                                                                                                        

laforge at rama%pts/11 (20:27) phone/src/libgsmd/atcmd >  2/1cu -l /dev/ttyUSB0 -s 1520015200
+Connected.
+
+OK
+ATV1
+OK
+AT+COPS=?
+ERROR
+AT+COPS=?
+ERROR
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
+ERROR
+
+OK
+
+OK
+AT+CRC=1
+OK
+AT+CRC=?
++CRC: (0,1)
+
+OK
+AT+CGMI
+<manufacturer>
+
+OK
+AT+GMM
+<model>
+
+OK
+AT+CGSI
+EXT: I
+
+ERROR
+AT+CGSS
+EXT: I
+
+ERROR
+AT+CGSS=?
+EXT: I
+
+ERROR
+AT+CGSS?
+EXT: I
+
+ERROR
+AT+CGSN
+<serial number>
+
+OK
+AT+CSCS?
++CSCS: "IRA"
+
+OK
+AT+CSCS=?
++CSCS: "GSM","IRA","PCCP437","PCDN","8859-1","HEX","UCS2"
+
+OK
+AT+CIMI?
+ERROR
+AT+CIMI
+262074992516579
+
+OK
+AT+M
+EXT: I
+
+ERROR
+AT+CMUX?
+OK
+AT-Command Interpreter ready
+
+OK
+AT+CMUX=?
++CMUX: (1),(0),(1-5),(10-100),(1-255),(0-100),(2-255),(1-255),(1-7)
+
+OK
+AT-Command Interpreter ready
+AT+CSTA
+ERROR
+AT+CSTA?
++CSTA: 129
+
+OK
+AT+CSTA=?
++CSTA: (129,145)
+
+OK
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+ATP
+ERROR
+AT+CPIN=9450
+ERROR
+AT+CMOD?
++CMOD: 0
+
+OK
+AT+CMOD=?
++CMOD: (0-3)
+
+OK
+
+OK
+AT+CHUP
+OK
+AT+CBST=?
++CBST: (0-7,12,14,65,66,68,70,71,75),(0),(0-3)
+
+OK
+AT
+ERROR
+AT+CRLP=?
++CRLP: (0-61),(0-61),(39-255),(1-255)
+
+OK
+
+OK
+AT+CR?
++CR: 0
+
+OK
+AT+CR=?
++CR: (0,1)
+
+OK
+AT+CR=1
+OK
+
+OK
+
+OK
+
+OK
+AT+CEER=1
++CEER: 0,1,1,255,no error
+
+OK
+AT+CEER?
+ERROR
+AT+CEER=?
+OK
+
+OK
+AT+CRC=1
+OK
+AT+CRC=?
++CRC: (0,1)
+
+OK
+AT+CSNS=?
+ERROR
+AT+CSNS?
++CSNS: 0
+
+OK
+AT+CSNS=?
++CSNS: (0-7)
+
+OK
+
+OK
+AT+CHVU?
+EXT: I
+
+ERROR
+AT+CVUHU?
+EXT: I
+
+ERROR
+AT+CVHU?
+EXT: I
+
+ERROR
+AT+CVHU=?
+EXT: I
+
+ERROR
+
+OK
+AT+CV120?
+EXT: I
+
+ERROR
+AT+CV120=?
+EXT: I
+
+ERROR
+
+OK
+AT+CNUM?
+ERROR
+AT+CNUM=?
+OK
+AT+CNUM?
+ERROR
+AT+CNUM=?
+OK
+AT+CREG?
++CREG: 0,2
+
+OK
+AT+CREG=?
++CREG: (0-2)
+
+OK
+AT
+ERROR
+ATC
+EXT: I
+
+ERROR
+AT+CREG=2
+OK
+
+OK
+AT+COPS=?
+ERROR
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
+ERROR
+
+OK
+AT+CLKS=?
+EXT: I
+
+ERROR
+AT+CLCK=?
++CLCK: ("SC","AO","OI","OX","AI","IR","AB","AG","AC","FD","PS","PN","PU","PP","PC","PF","AL")
+
+OK
+
+OK
+AT+CLIP=?
++CLIP: (0,1)
+
+OK
+ATP
+ERROR
+AT+CLIP?
++CLIP: 0,2
+
+OK
+AT+CLIR=?
++CLIR: (0,1,2)
+
+OK
+AT+CLIR?
++CLIR: 0,2
+
+OK
+AT+COPLP+
+EXT: I
+
+ERROR
+AT+COLP?
++COLP: 0,2
+
+OK
+AT+COLP=?
++COLP: (0,1)
+
+OK
+AT+CCFG
+EXT: I
+
+ERROR
+a
+ERROR
+AT+CCFC?
+ERROR
+AT+CCFC=?
++CCFC: (0-5)
+
+OK
+AT+CCWA
+OK
+AT+CCWA?
++CCWA: 0
+
+OK
+AT+CCWA=?
++CCWA: (0,1)
+
+OK
+
+OK
+AT+CCWA=1
+OK
+
+OK
+AT+CTFR=?
+OK
+AT+CTFR?
+ERROR
+
+OK
+AT+CUSD=?
++CUSD: (0,1,2)
+
+OK
+AT+CUSD?
++CUSD: 0
+
+OK
+AT+CUSD=1
+OK
+AT+CCSN?
+EXT: I
+
+ERROR
+AT+CCSN=?
+EXT: I
+
+ERROR
+
+OK
+AT+CCSI?
+EXT: I
+
+ERROR
+AT
+ERROR
+AT+CLCC?
+ERROR
+AT+CLCC=?
+OK
+
+OK
+AT+CPOL?
+ERROR
+AT+CPOL=?
+ERROR
+AT+
+ERROR
+AT+COPN?
+ERROR
+AT+COPN=?
+OK
+
+OK
+AT+CPAS?
+ERROR
+AT+CPAS=?
++CPAS: (0-5)
+
+OK
+AT+CPAS
++CPAS: 0
+
+OK
+
+OK
+AT+CMEC?
+EXT: I
+
+ERROR
+AT+CMEC=?
+EXT: I
+
+ERROR
+AT+CFUN?
++CFUN: 1
+
+OK
+AT+CFUN=?
++CFUN: (0,1,4),(0)
+
+OK
+
+OK
+AT+PIN
+EXT: I
+
+ERROR
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+AT+CPIN=9450
+ERROR
+
++CREG: 2
+
+OK
+AT+CPIN?
++CPIN: READY
+
+OK
+AT+CBC?
+ERROR
+AT+CBC=?
++CBC: (0-3),(0-100)
+
+OK
+AT+CBC
++CBC: 0,0
+
+OK
+AT+CBC
++CBC: 0,0
+
+OK
+AT+CBC
++CBC: 0,0
+
+OK
+AT+CSQ?
+ERROR
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
AT-Command Interpreter ready
+
+OK
+
+OK
+AT+CPIN
+ERROR
+AT+CPIN?
++CPIN: SIM PIN
+
+OK
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS?
++COPS: 0
+
+OK
+AT+CPAS?
+ERROR
+AT+CAP
+EXT: I
+
+ERROR
+AT+CPAS
++CPAS: 0
+
+OK
+AT+COPS?
++COPS: 0
+
+OK
+AT+COPS=?
AT-Command Interpreter ready
+AT+CPIN?
++CPIN: READY
+
+OK
+AT+CMEC
+EXT: I
+
+ERROR
+AT+CMEC?
+EXT: I
+
+ERROR
+AT+CDIS?
+EXT: I
+
+ERROR
+AT+CIND?
++CIND: 0,0
+
+OK
+AT+CIND=/?
+OK
+AT+CIND=?
++CIND: ("signal", (0-5)), ("smsfull", (0-1))
+
+OK
+AT+CMER?
++CMER: 0,0,0,0,0
+
+OK
+AT+CMER=?
++CMER: (0-2), (0), (0), (0-2), (0,1)
+
+OK
+cu: Got hangup signal
+
+Disconnected.
+%                                                                                                        

laforge at rama%pts/11 (22:31) phone/src/libgsmd/atcmd >  3/0
\ No newline at end of file

Added: trunk/src/target/gsm/src/gsmd/.gpsd.h.swp
===================================================================
(Binary files differ)


Property changes on: trunk/src/target/gsm/src/gsmd/.gpsd.h.swp
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/target/gsm/src/gsmd/Makefile
===================================================================
--- trunk/src/target/gsm/src/gsmd/Makefile	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/Makefile	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,14 @@
+
+CFLAGS:=-I../../include -Wall -g
+gsmd_OBJS:=gsmd.o atcmd.o select.o vendor_ti.o usock.o unsolicited.o
+
+all: gsmd
+
+gsmd: $(gsmd_OBJS)
+	$(CC) -o $@ $^
+
+%.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $^
+
+clean:
+	rm -f $(gsmd_OBJS) gsmd

Added: trunk/src/target/gsm/src/gsmd/atcmd.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/atcmd.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/atcmd.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,332 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+
+#include <common/linux_list.h>
+#include "gsmd.h"
+#include "atcmd.h"
+#include "unsolicited.h"
+
+/* libgsmd / gsmd AT command interpreter / parser / constructor
+ * (C) 2006 by Harald Welte <hwelte at hmw-consulting.de>
+ *
+ * Written for First International Computer, Inc., Taiwan
+ */ 
+
+enum final_result_codes {
+	GSMD_RESULT_OK = 0,
+	GSMD_RESULT_ERR = 1,
+	NUM_FINAL_RESULTS,
+};
+
+static const char *final_results[] = {
+	"OK",
+	"ERROR",
+	"+CME ERROR:"
+};
+
+/* we basically implement a parse that can deal with
+ * - receiving and queueing commands from higher level of libgmsd
+ * - optionally combining them into one larger command (; appending)
+ * - sending those commands to the TA, receiving and parsing responses
+ * - calling back application on completion, or waiting synchronously
+ *   for a response
+ * - dealing with intermediate and unsolicited resultcodes by calling
+ *   back into the application / higher levels
+ */
+
+static inline int llparse_append(struct llparser *llp, char byte)
+{
+	if (llp->cur < llp->buf + llp->len) {
+		*(llp->cur++) = byte;
+		return 0;
+	} else
+		return -EFBIG;
+}
+
+static int llparse_byte(struct llparser *llp, char byte)
+{
+	int ret = 0;
+
+	switch (llp->state) {
+	case LLPARSE_STATE_IDLE:
+		if (llp->flags & LGSM_ATCMD_F_EXTENDED) {
+			if (byte == '\r')
+				llp->state = LLPARSE_STATE_IDLE_CR;
+			else {
+#ifdef STRICT
+				llp->state = LLPARSE_STATE_ERROR;
+#else
+				llp->state = LLPARSE_STATE_RESULT;
+				ret = llparse_append(llp, byte);
+#endif
+			}
+		} else {
+			llp->state = LLPARSE_STATE_RESULT;
+			ret = llparse_append(llp, byte);
+		}
+		break;
+	case LLPARSE_STATE_IDLE_CR:
+		if (byte == '\n')
+			llp->state = LLPARSE_STATE_IDLE_LF;
+		else
+			llp->state = LLPARSE_STATE_ERROR;
+		break;
+	case LLPARSE_STATE_IDLE_LF:
+		/* can we really go directly into result_cr ? */
+		if (byte == '\r')
+			llp->state = LLPARSE_STATE_RESULT_CR;
+		else {
+			llp->state = LLPARSE_STATE_RESULT;
+			ret = llparse_append(llp, byte);
+		}
+		break;
+	case LLPARSE_STATE_RESULT:
+		if (byte == '\r')
+			llp->state = LLPARSE_STATE_RESULT_CR;
+		else
+			ret = llparse_append(llp, byte);
+		break;
+	case LLPARSE_STATE_RESULT_CR:
+		if (byte == '\n')
+			llp->state = LLPARSE_STATE_IDLE;
+		break;
+	case LLPARSE_STATE_ERROR:
+		break;
+	}
+
+	return ret;
+}
+
+static int llparse_string(struct llparser *llp, char *buf, unsigned int len)
+{
+	while (len--) {
+		int rc = llparse_byte(llp, *(buf++));
+		if (rc < 0)
+			return rc;
+
+		/* if _after_ parsing the current byte we have finished,
+		 * let the caller know that there is something to handle */
+		if (llp->state == LLPARSE_STATE_RESULT_CR) {
+			llp->cb(llp->buf, llp->cur - llp->buf, llp->ctx);
+			/* re-set cursor to start of buffer */
+			llp->cur = llp->buf;
+		}
+	}
+
+	return 0;
+}
+
+/* mid-level parser */
+
+static int parse_final_result(const char *res)
+{
+	int i;
+	for (i = 0; i < NUM_FINAL_RESULTS; i++) {
+		if (!strcmp(res, final_results[i]))
+			return i;
+	}
+	
+	return -1;
+}
+
+static int ml_parse(const char *buf, int len, void *ctx)
+{
+	struct gsmd *g = ctx;
+	struct gsmd_atcmd *cmd;
+	int final = 0;
+	
+	/* responses come in order, so first response has to be for first
+	 * command we sent, i.e. first entry in list */
+	cmd = llist_entry(g->busy_atcmds.next, struct gsmd_atcmd, list);
+
+	if (buf[0] == '+') {
+		/* an extended response */
+		const char *colon = strchr(buf, ':');
+		if (!colon) {
+			fprintf(stderr, "no colon in extd response `%s'\n",
+				buf);
+			return -EINVAL;
+		}
+		if (cmd->buf[2] != '+') {
+			fprintf(stderr, "extd reply to non-extd command?\n");
+			return -EINVAL;
+		}
+
+		if (!strncmp(buf+1, "CME ERROR", 9)) {
+			unsigned long err_nr;
+			err_nr = strtoul(colon+1, NULL, 10);
+			DEBUGP("error number %lu\n", err_nr);
+			cmd->ret = err_nr;
+			final = 1;
+			goto final_cb;
+		}
+
+		if (strncmp(buf, &cmd->buf[2], colon-buf)) {
+			DEBUGP("extd reply `%s' to cmd `%s', must be "
+			       "unsolicited\n", buf, &cmd->buf[2]);
+			colon++;
+			if (colon > buf+len)
+				colon = NULL;
+			return unsolicited_parse(g, buf, len, colon);
+		}
+
+		/* if we survive till here, it's a valid extd response
+		 * to an extended command */
+
+		/* FIXME: solve multi-line responses ! */
+		if (cmd->buflen < len)
+			len = cmd->buflen;
+
+		memcpy(cmd->buf, buf, len);
+	} else {
+
+		/* this is the only non-extended unsolicited return code */
+		if (!strcmp(buf, "RING"))
+			return unsolicited_parse(g, buf, len, NULL);
+
+		if (!strcmp(buf, "ERROR") ||
+		    ((g->flags & GSMD_FLAG_V0) && cmd->buf[0] == '4')){
+			DEBUGP("unspecified error\n");
+			cmd->ret = 4;
+			final = 1;
+			goto final_cb;
+		}
+
+		if (!strncmp(buf, "OK", 2)
+		    || ((g->flags & GSMD_FLAG_V0) && cmd->buf[0] == '0')) {
+			cmd->ret = 0;
+			final = 1;
+			goto final_cb;
+		}
+
+		/* FIXME: handling of those special commands in response to
+		 * ATD / ATA */
+		if (!strncmp(buf, "NO CARRIER", 10)) {
+		}
+
+		if (!strncmp(buf, "BUSY", 4)) {
+		}
+	}
+
+final_cb:
+	if (final) {
+		/* remove from list of currently executing cmds */
+		llist_del(&cmd->list);
+
+		if (cmd->cb) {
+			fprintf(stderr, "command without cb!!!\n");
+			return -EINVAL;
+		}
+		return cmd->cb(cmd, cmd->ctx);
+
+	}
+
+	return 0;
+}
+
+/* callback to be called if [virtual] UART has some data for us */
+static int atcmd_select_cb(int fd, unsigned int what, void *data)
+{
+	int len;
+	static char rxbuf[1024];
+	struct gsmd *g = data;
+
+	if (what & GSMD_FD_READ) {
+		while ((len = read(fd, rxbuf, sizeof(rxbuf)))) {
+			int rc; 
+	
+			if (len < 0) {
+				DEBUGP("ERROR reading from fd %u: %d (%s)\n", fd, len,
+					strerror(errno));
+					return len;
+			}
+			rc = llparse_string(&g->llp, rxbuf, len);
+			if (rc < 0) {
+				DEBUGP("ERROR during llparse_string: %d\n", rc);
+				return rc;
+			}
+		}
+	}
+
+	/* write pending commands to UART */
+	if (what & GSMD_FD_WRITE) {
+		struct gsmd_atcmd *pos, *pos2;
+		llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
+			int rc = write(fd, pos->buf, strlen(pos->buf));
+			if (rc == 0) {
+				DEBUGP("write returns 0, aborting\n");
+				break;
+			} else if (rc < 0) {
+				DEBUGP("error during write to fd %d: %d\n",
+					fd, rc);
+				return rc;
+			}
+			if (rc < len) {
+				fprintf(stderr, "short write!!! FIXME!\n");
+				exit(3);
+			}
+			/* success: remove from global list of to-be-sent atcmds */
+			llist_del(&pos->list);
+			/* append to global list of executing atcmds */
+			llist_add_tail(&pos->list, &g->busy_atcmds);
+		}
+	}
+
+	return 0;
+}
+
+
+struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen,
+			      atcmd_cb_t cb, void *ctx)
+{
+	int buflen = strlen(cmd);
+	struct gsmd_atcmd *atcmd;
+	
+	if (rlen > buflen)
+		buflen = rlen;
+	
+	atcmd = malloc(sizeof(*atcmd)+ buflen);
+	if (!atcmd)
+		return NULL;
+
+	atcmd->ctx = ctx;
+	atcmd->flags = 0;
+	atcmd->ret = -255;
+	atcmd->buflen = buflen;
+	atcmd->buf[buflen-1] = '\0';
+	atcmd->cb = cb;
+	strncpy(atcmd->buf, cmd, buflen-1);
+
+	return atcmd;
+}
+
+/* submit an atcmd in the global queue of pending atcmds */
+int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd)
+{
+	llist_add_tail(&cmd->list, &g->pending_atcmds);
+	g->gfd_uart.when |= GSMD_FD_WRITE;
+
+	return 0;
+}
+
+/* init atcmd parser */
+int atcmd_init(struct gsmd *g, int sockfd)
+{
+	g->gfd_uart.fd = sockfd;
+	g->gfd_uart.when = GSMD_FD_READ;
+	g->gfd_uart.data = g;
+	g->gfd_uart.cb = &atcmd_select_cb;
+
+	g->llp.cur = g->llp.buf;
+	g->llp.cb = &ml_parse;
+	g->llp.ctx = g;
+	g->llp.flags = LGSM_ATCMD_F_EXTENDED;
+
+	return gsmd_register_fd(&g->gfd_uart);
+}	
+

Added: trunk/src/target/gsm/src/gsmd/atcmd.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/atcmd.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/atcmd.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,12 @@
+#ifndef __GSMD_ATCMD_H
+#define __GSMD_ATCMD_H
+
+#include "gsmd.h"
+
+typedef int atcmd_cb_t(struct gsmd_atcmd *cmd, void *ctx);
+
+struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen, atcmd_cb_t *cb, void *ctx);
+int atcmd_submit(struct gsmd *g, struct gsmd_atcmd *cmd);
+int atcmd_init(struct gsmd *g, int sockfd);
+
+#endif

Added: trunk/src/target/gsm/src/gsmd/gsmd.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/gsmd.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/gsmd.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,171 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <gsmd/gsmd.h>
+
+#include "gsmd.h"
+#include "atcmd.h"
+#include "select.h"
+#include "usock.h"
+#include "vendorplugin.h"
+
+static int gsmd_test_atcb(struct gsmd_atcmd *cmd, void *ctx)
+{
+	printf("returned: `%s'\n", cmd->buf);
+	free(cmd);
+	return 0;
+}
+
+static int gsmd_test(struct gsmd *gsmd)
+{
+	struct gsmd_atcmd *cmd;
+	cmd = atcmd_fill("AT+CLCK=?", 255, &gsmd_test_atcb, NULL);
+	return atcmd_submit(gsmd, cmd);
+}
+
+struct bdrt {
+	int bps;
+	u_int32_t b;
+};
+
+static struct bdrt bdrts[] = {
+	{ 0, B0 },
+	{ 9600, B9600 },
+	{ 19200, B19200 },
+	{ 38400, B38400 },
+	{ 57600, B57600 },
+	{ 115200, B115200 },
+};
+
+static int set_baudrate(int fd, int baudrate)
+{
+	int i;
+	u_int32_t bd = 0;
+	struct termios ti;
+
+	for (i = 0; i < ARRAY_SIZE(bdrts); i++) {
+		if (bdrts[i].bps == baudrate)
+			bd = bdrts[i].b;
+	}
+	if (bd == 0)
+		return -EINVAL;
+	
+	i = tcgetattr(fd, &ti);
+	if (i < 0)
+		return i;
+	
+	i = cfsetispeed(&ti, B0);
+	if (i < 0)
+		return i;
+	
+	i = cfsetospeed(&ti, bd);
+	if (i < 0)
+		return i;
+	
+	return tcsetattr(fd, 0, &ti);
+}
+
+
+static struct gsmd g;
+
+static struct option opts[] = {
+	{ "version", 0, NULL, 'V' },
+	{ "daemon", 0, NULL, 'd' },
+	{ "help", 0, NULL, 'h' },
+	{ "device", 1, NULL, 'p' },
+	{ "speed", 1, NULL, 's' },
+};
+
+int main(int argc, char **argv)
+{
+	int fd, argch; 
+
+	int daemonize = 0;
+	int bps = 115200;
+	char *device = "/dev/ttyUSB0";
+
+	/*FIXME: parse commandline, set daemonize, device, ... */
+	while ((argch = getopt_long(argc, argv, "Vdhps:", opts, NULL)) != -1) {
+		switch (argch) {
+		case 'V':
+			/* FIXME */
+			break;
+		case 'd':
+			daemonize = 1;
+			break;
+		case 'h':
+			/* FIXME */
+			break;
+		case 'p':
+			device = optarg;
+			break;
+		case 's':
+			bps = atoi(optarg);
+			break;
+		}
+	}
+
+	/* use direct access to device node ([virtual] tty device) */
+	fd = open(device, O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "can't open device `%s': %s\n",
+			device, strerror(errno));
+		exit(1);
+	}
+
+	if (set_baudrate(fd, bps) < 0) {
+		fprintf(stderr, "can't set baudrate\n");
+		exit(1);
+	}
+
+	if (atcmd_init(&g, fd) < 0) {
+		fprintf(stderr, "can't initialize UART device\n");
+		exit(1);
+	}
+
+	if (usock_init(&g) < 0) {
+		fprintf(stderr, "can't open unix socket\n");
+		exit(1);
+	}
+
+	if (daemonize) {
+		if (fork()) {
+			exit(0);
+		}
+		fclose(stdout);
+		fclose(stderr);
+		fclose(stdin);
+		setsid();
+	}
+
+	gsmd_test(&g);
+
+	while (1) {
+		int ret = gsmd_select_main();
+		if (ret == 0)
+			continue;
+
+		if (ret < 0) {
+			if (errno == -EINTR)
+				continue;
+			else {
+				DEBUGP("select returned error (%s)\n",
+					strerror(errno));
+				break;
+			}
+		}
+	}
+
+	exit(0);
+}

Added: trunk/src/target/gsm/src/gsmd/gsmd.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/gsmd.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/gsmd.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,68 @@
+#ifndef __GSMD_H
+#define __GSMD_H
+
+#include <sys/types.h>
+
+#include <common/linux_list.h>
+
+#include "select.h"
+
+/* Refer to 3GPP TS 07.07 v 7.8.0, Chapter 4.1 */
+#define LGSM_ATCMD_F_EXTENDED	0x01	/* as opposed to basic */
+#define LGSM_ATCMD_F_PARAM	0x02	/* as opposed to action */
+
+struct gsmd_atcmd {
+	struct llist_head list;
+	void *ctx;
+	int (*cb)(struct gsmd_atcmd *, void *);
+	u_int8_t flags;
+	int32_t ret;
+	u_int32_t buflen;
+	char buf[];
+};
+
+enum llparse_state {
+	LLPARSE_STATE_IDLE,		/* idle, not parsing a response */
+	LLPARSE_STATE_IDLE_CR,		/* CR before response (V1) */
+	LLPARSE_STATE_IDLE_LF,		/* LF before response (V1) */
+	LLPARSE_STATE_RESULT,		/* within result payload */
+	LLPARSE_STATE_RESULT_CR,	/* CR after result */
+	LLPARSE_STATE_ERROR,		/* something went wrong */
+					/* ... idle again */
+};
+
+/* we can't take any _single_ response bigger than this: */
+#define LLPARSE_BUF_SIZE	256
+
+struct llparser {
+	enum llparse_state state;
+	unsigned int len;
+	unsigned int flags;
+	void *ctx;
+	int (*cb)(const char *buf, int len, void *ctx);
+	char *cur;
+	char buf[LLPARSE_BUF_SIZE];
+};
+
+#define GSMD_FLAG_V0		0x0001	/* V0 responses to be expected from TA */
+
+struct gsmd {
+	unsigned int flags;
+	struct gsmd_fd gfd_uart;
+	struct gsmd_fd gfd_sock;
+	struct llparser llp;
+	struct llist_head users;
+	struct llist_head pending_atcmds;	/* our busy gsmd_atcmds */
+	struct llist_head busy_atcmds;	/* our busy gsmd_atcmds */
+};
+
+struct gsmd_user {
+	struct llist_head list;		/* our entry in the global list */
+	struct llist_head finished_ucmds;	/* our busy gsmd_ucmds */
+	struct gsmd *gsmd;
+	struct gsmd_fd gfd;				/* the socket */
+	u_int32_t subscriptions;		/* bitmaks of subscribed event groups */
+};
+
+#define DEBUGP(x, args ...)	printf("%s:%s(%d):" x, __FILE__, __FUNCTION__, __LINE__, ## args)
+#endif

Added: trunk/src/target/gsm/src/gsmd/gsmd_event.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/gsmd_event.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/gsmd_event.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,53 @@
+#ifndef __GSMD_EVENT_H
+#define __GSMD_EVENT_H
+
+/* event handling */
+
+enum gsmd_event_type {
+	GSMD_EVTTYPE_NONE,
+	GSMD_EVTTYPE_VOICECALL,
+	GSMD_EVTTYPE_DATACALL,
+	GSMD_EVTTYPE_SMS,
+	GSMD_EVTTYPE_GPRS,
+	GSMD_EVTTYPE_CIPHER_IND,
+};
+
+enum gsmd_event_call {
+	GSMD_EVT_CALL_NONE,
+	GSMD_EVT_CALL_HANGUP,		/* any call: hanged up */
+	GSMD_EVT_CALL_RING,		/* incoming call: we're ringing */ 
+	GSMD_EVT_CALL_BUSY,		/* outgoing call: busy */
+	GSMD_EVT_CALL_RINGING,		/* outgoing call: other end ringing */
+	GSMD_EVT_CALL_ESTABLISHED,	/* any call: now established */
+};
+
+enum gsmd_event_voice {
+	/* all of event_call */
+};
+
+enum gsmd_event_data {
+	/* all of event_call */
+};
+
+enum gsmd_event_sms {
+	GSMD_EVT_SMS_NONE,
+	GSMD_EVT_SMS_RCVD,		/* incoming SMS received */
+	GSMD_EVT_SMS_OVERFLOW,		/* sms memory full, can't receive */
+};
+
+enum gsmd_event_gprs {
+};
+
+enum gsmd_event_cipher {
+	GSMD_EVT_CI_NONE,
+	GSMD_EVT_CI_ENABLED,		/* cipher enabled */
+	GSMD_EVT_CI_DISABLED,		/* cipher disabled */
+};
+
+enum gsmd_event_network {
+	GSMD_EVT_NW_NONE,
+	GSMD_EVT_NW_SIGNAL,		/* signal strength */
+	GSMD_EVT_NW_REG,		/* network registration */
+};
+
+#endif

Added: trunk/src/target/gsm/src/gsmd/select.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/select.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/select.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,96 @@
+/* select() FD handling for GSM Daemon.
+ * (C) 2000-2006 by Harald Welte <laforge at gnumonks.org>
+ *
+ * Based on code originally written by myself for ulogd.
+ *
+ *  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 <common/linux_list.h>
+#include "select.h"
+
+static int maxfd = 0;
+static LLIST_HEAD(gsmd_fds);
+
+int gsmd_register_fd(struct gsmd_fd *fd)
+{
+	int flags;
+
+	/* make FD nonblocking */
+	flags = fcntl(fd->fd, F_GETFL);
+	if (flags < 0)
+		return -1;
+	flags |= O_NONBLOCK;
+	flags = fcntl(fd->fd, F_SETFL, flags);
+	if (flags < 0)
+		return -1;
+
+	/* Register FD */
+	if (fd->fd > maxfd)
+		maxfd = fd->fd;
+
+	llist_add_tail(&fd->list, &gsmd_fds);
+
+	return 0;
+}
+
+void gsmd_unregister_fd(struct gsmd_fd *fd)
+{
+	llist_del(&fd->list);
+}
+
+int gsmd_select_main()
+{
+	struct gsmd_fd *ufd;
+	fd_set readset, writeset, exceptset;
+	int i;
+
+	FD_ZERO(&readset);
+	FD_ZERO(&writeset);
+	FD_ZERO(&exceptset);
+
+	/* prepare read and write fdsets */
+	llist_for_each_entry(ufd, &gsmd_fds, list) {
+		if (ufd->when & GSMD_FD_READ)
+			FD_SET(ufd->fd, &readset);
+
+		if (ufd->when & GSMD_FD_WRITE)
+			FD_SET(ufd->fd, &writeset);
+
+		if (ufd->when & GSMD_FD_EXCEPT)
+			FD_SET(ufd->fd, &exceptset);
+	}
+
+	i = select(maxfd+1, &readset, &writeset, &exceptset, NULL);
+	if (i > 0) {
+		/* call registered callback functions */
+		llist_for_each_entry(ufd, &gsmd_fds, list) {
+			int flags = 0;
+
+			if (FD_ISSET(ufd->fd, &readset))
+				flags |= GSMD_FD_READ;
+
+			if (FD_ISSET(ufd->fd, &writeset))
+				flags |= GSMD_FD_WRITE;
+
+			if (FD_ISSET(ufd->fd, &exceptset))
+				flags |= GSMD_FD_EXCEPT;
+
+			if (flags)
+				ufd->cb(ufd->fd, flags, ufd->data);
+		}
+	}
+	return i;
+}

Added: trunk/src/target/gsm/src/gsmd/select.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/select.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/select.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,22 @@
+#ifndef __GSMD_SELECT_H
+#define __GSMD_SELECT_H
+
+#include <common/linux_list.h>
+
+#define GSMD_FD_READ	0x0001
+#define GSMD_FD_WRITE	0x0002
+#define GSMD_FD_EXCEPT	0x0004
+
+struct gsmd_fd {
+	struct llist_head list;
+	int fd;				/* file descriptor */
+	unsigned int when;
+	int (*cb)(int fd, unsigned int what, void *data);
+	void *data;			/* void * to pass to callback */
+};
+
+int gsmd_register_fd(struct gsmd_fd *ufd);
+void gsmd_unregister_fd(struct gsmd_fd *ufd);
+int gsmd_select_main(void);
+
+#endif

Added: trunk/src/target/gsm/src/gsmd/unsolicited.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/unsolicited.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/unsolicited.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,272 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#include "gsmd.h"
+#include "usock.h"
+
+static struct gsmd_ucmd *build_event(u_int8_t type, u_int8_t subtype, u_int8_t len)
+{
+	struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+len);
+
+	if (!ucmd)
+		return NULL;
+
+	ucmd->hdr.version = GSMD_PROTO_VERSION;
+	ucmd->hdr.msg_type = type;
+	ucmd->hdr.msg_subtype = subtype;
+	ucmd->hdr.len = len;
+
+	return ucmd;
+}
+
+static struct gsmd_ucmd *ucmd_copy(const struct gsmd_ucmd *orig)
+{
+	int size = sizeof(*orig) + orig->hdr.len;
+	struct gsmd_ucmd *copy = malloc(size);
+
+	if (copy)
+		memcpy(copy, orig, size);
+
+	return copy;
+}
+
+static int usock_evt_send(struct gsmd *gsmd, struct gsmd_ucmd *ucmd, u_int32_t evt)
+{
+	struct gsmd_user *gu;
+	int num_sent = 0;
+
+	llist_for_each_entry(gu, &gsmd->users, list) {
+		if (gu->subscriptions & (1 << evt)) {
+			struct gsmd_ucmd *cpy = ucmd_copy(ucmd);
+			llist_add_tail(&ucmd->list, &gu->finished_ucmds);
+			num_sent++;
+			ucmd = cpy;
+			if (!ucmd) {
+				fprintf(stderr, "can't allocate memory for copy of ucmd\n");
+				return num_sent;
+			}
+		}
+	}
+
+	return num_sent;
+}
+
+static int ring_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	/* FIXME: generate ring event */
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL,
+					     sizeof(struct gsmd_evt_auxdata));	
+	struct gsmd_evt_auxdata *aux;
+	if (!ucmd)
+		return -ENOMEM;
+
+	aux = (struct gsmd_evt_auxdata *)ucmd->buf;
+
+	aux->u.call.type = GSMD_CALL_UNSPEC;
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL);
+}
+
+static int cring_parse(const char *buf, int len, const char *param, struct gsmd *gsmd)
+{
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL,
+					     sizeof(struct gsmd_evt_auxdata));
+	struct gsmd_evt_auxdata *aux;
+	if (!ucmd)
+		return -ENOMEM;
+
+	aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+	if (!strcmp(param, "VOICE")) {
+		/* incoming voice call */
+		aux->u.call.type = GSMD_CALL_VOICE;
+	} else if (!strcmp(param, "SYNC")) {
+		aux->u.call.type = GSMD_CALL_DATA_SYNC;
+	} else if (!strcmp(param, "REL ASYNC")) {
+		aux->u.call.type = GSMD_CALL_DATA_REL_ASYNC;
+	} else if (!strcmp(param, "REL SYNC")) {
+		aux->u.call.type = GSMD_CALL_DATA_REL_SYNC;
+	} else if (!strcmp(param, "FAX")) {
+		aux->u.call.type = GSMD_CALL_FAX;
+	} else if (!strncmp(param, "GPRS ", 5)) {
+		/* FIXME: change event type to GPRS */
+		free(ucmd);
+		return 0;
+	}
+	/* FIXME: parse all the ALT* profiles, Chapter 6.11 */
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL);
+}
+
+/* Chapter 7.2, network registration */
+static int creg_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	const char *comma = strchr(param, ',');
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_NETREG,
+					     sizeof(struct gsmd_evt_auxdata));
+	struct gsmd_evt_auxdata *aux;
+	if (!ucmd)
+		return -ENOMEM;
+	aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+	aux->u.netreg.state = atoi(param);
+	if (comma) {
+		/* FIXME: we also have location area code and cell id to parse (hex) */
+	}
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_NETREG);
+}
+
+/* Chapter 7.11, call waiting */
+static int ccwa_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	const char *number;
+	u_int8_t type, class;
+
+	/* FIXME: parse */
+	return 0;
+}
+
+/* Chapter 7.14, unstructured supplementary service data */
+static int cusd_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	/* FIXME: parse */
+	return 0;
+}
+
+/* Chapter 7.15, advise of charge */
+static int cccm_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	/* FIXME: parse */
+	return 0;
+}
+
+/* Chapter 10.1.13, GPRS event reporting */
+static int cgev_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	/* FIXME: parse */
+	return 0;
+}
+
+/* Chapter 10.1.14, GPRS network registration status */
+static int cgreg_parse(const char *buf, int len, const char *param,
+		       struct gsmd *gsmd)
+{
+	/* FIXME: parse */
+	return 0;
+}
+
+/* Chapter 7.6, calling line identification presentation */
+static int clip_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CLIP,
+					     sizeof(struct gsmd_evt_auxdata));
+	struct gsmd_evt_auxdata *aux;
+	const char *comma = strchr(param, ',');
+
+	if (!ucmd)
+		return -ENOMEM;
+	
+	aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+	if (!comma)
+		return -EINVAL;
+	
+	if (comma - param > GSMD_ADDR_MAXLEN)
+		return -EINVAL;
+
+	memcpy(aux->u.clip.addr.number, param, comma-param);
+	/* FIXME: parse of subaddr, etc. */
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CLIP);
+}
+
+/* Chapter 7.9, calling line identification presentation */
+static int colp_parse(const char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_OUT_COLP,
+					     sizeof(struct gsmd_evt_auxdata));
+	struct gsmd_evt_auxdata *aux;
+	const char *comma = strchr(param, ',');
+
+	if (!ucmd)
+		return -ENOMEM;
+	
+	aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+	if (!comma)
+		return -EINVAL;
+	
+	if (comma - param > GSMD_ADDR_MAXLEN)
+		return -EINVAL;
+
+	memcpy(aux->u.colp.addr.number, param, comma-param);
+	/* FIXME: parse of subaddr, etc. */
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_COLP);
+}
+
+struct gsmd_unsolicit {
+	const char *prefix;
+	int (*parse)(const char *unsol, int len, const char *param, struct gsmd *gsmd);
+};
+
+static const struct gsmd_unsolicit gsm0707_unsolicit[] = {
+	{ "RING",	&ring_parse },
+	{ "+CRING", 	&cring_parse },
+	{ "+CREG",	&creg_parse },
+	{ "+CCWA",	&ccwa_parse },
+	{ "+CUSD",	&cusd_parse },
+	{ "+CCCM",	&cccm_parse },
+	{ "+CGEV",	&cgev_parse },
+	{ "+CGREG",	&cgreg_parse },
+	{ "+CLIP",	&clip_parse },
+	{ "+COLP",	&colp_parse },
+	/*
+	{ "+CKEV",	&ckev_parse },
+	{ "+CDEV",	&cdev_parse },
+	{ "+CIEV",	&ciev_parse },
+	{ "+CLAV",	&clav_parse },
+	{ "+CCWV",	&ccwv_parse },
+	{ "+CLAV",	&clav_parse },
+	{ "+CSSU",	&cssu_parse },
+	*/
+};
+
+/* called by midlevel parser if a response seems unsolicited */
+int unsolicited_parse(struct gsmd *g, const char *buf, int len, const char *param)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gsm0707_unsolicit); i++) {
+		const char *colon;
+		if (strncmp(buf, gsm0707_unsolicit[i].prefix,
+			     strlen(gsm0707_unsolicit[i].prefix)))
+			continue;
+		
+		colon = strchr(buf, ':') + 1;
+		if (colon > buf+len)
+			colon = NULL;
+
+		return gsm0707_unsolicit[i].parse(buf, len, colon, g);
+	}
+
+	/* FIXME: call vendor-specific unsolicited code parser */
+	return -EINVAL;
+}
+

Added: trunk/src/target/gsm/src/gsmd/unsolicited.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/unsolicited.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/unsolicited.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,8 @@
+#ifndef __GSMD_UNSOLICITED_H
+#define __GSMD_UNSOLICITED_H
+
+#include "gsmd.h"
+
+int unsolicited_parse(struct gsmd *g, const char *buf, int len, const char *param);
+
+#endif

Added: trunk/src/target/gsm/src/gsmd/usock.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/usock.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/usock.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,166 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <gsmd/gsmd.h>
+#include <gsmd/usock.h>
+
+#include "gsmd.h"
+#include "select.h"
+#include "atcmd.h"
+#include "usock.h"
+
+/* callback for completed passthrough gsmd_atcmd's */
+static int usock_cmd_cb(struct gsmd_atcmd *cmd, void *ctx)
+{
+	struct gsmd_user *gu = ctx;
+	struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+cmd->buflen);
+
+	if (!ucmd)
+		return -ENOMEM;
+	
+	ucmd->hdr.version = GSMD_PROTO_VERSION;
+	ucmd->hdr.msg_type = GSMD_MSG_PASSTHROUGH;
+	ucmd->hdr.msg_subtype = GSMD_PASSTHROUGH_RESP;
+	ucmd->hdr.len = cmd->buflen;
+	memcpy(ucmd->buf, cmd->buf, ucmd->hdr.len);
+
+	/* add to per-user list of finished cmds */
+	llist_add_tail(&ucmd->list, &gu->finished_ucmds);
+
+	/* mark socket of user as we-want-to-write */
+	gu->gfd.when |= GSMD_FD_WRITE;
+
+	return 0;
+}
+
+static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
+{
+	struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;
+
+	if (gph->version != GSMD_PROTO_VERSION)
+		return -EINVAL;
+
+	switch (gph->msg_type) {
+	case GSMD_MSG_PASSTHROUGH: 
+		{
+			struct gsmd_atcmd *cmd;
+			cmd = atcmd_fill((char *)gph+sizeof(*gph),
+					 255, &usock_cmd_cb, gu);
+			if (!cmd)
+				return -ENOMEM;
+			return atcmd_submit(gu->gsmd, cmd);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* callback for read/write on client (libgsmd) socket */
+static int gsmd_usock_user_cb(int fd, unsigned int what, void *data)
+{
+	struct gsmd_user *gu = data;
+
+	/* FIXME: check some kind of backlog and limit it */
+
+	if (what & GSMD_FD_READ) {
+		char buf[1024];
+		int rcvlen;
+		/* read data from socket, determine what he wants */
+		rcvlen = read(fd, buf, sizeof(buf));
+		return usock_rcv_pcmd(gu, buf, rcvlen);
+	}
+
+	if (what & GSMD_FD_WRITE) {
+		/* write data from pending replies to socket */
+		struct gsmd_ucmd *ucmd, *uctmp;
+		llist_for_each_entry_safe(ucmd, uctmp, &gu->finished_ucmds,
+					  list) {
+			int rc;
+
+			rc = write(fd, &ucmd->hdr, sizeof(ucmd->hdr) + ucmd->hdr.len);
+			if (rc < 0) {
+				DEBUGP("write return %d\n", rc);
+				return rc;
+			}
+			if (rc == 0) {
+				DEBUGP("write returns zero!!\n");
+				break;
+			}
+			if (rc != sizeof(ucmd->hdr) + ucmd->hdr.len) {
+				DEBUGP("short write\n");
+				break;
+			}
+
+			llist_del(&ucmd->list);
+			free(ucmd);
+		}
+	}
+
+	return 0;
+}
+
+/* callback for read on master-listen-socket */
+static int gsmd_usock_cb(int fd, unsigned int what, void *data)
+{
+	struct gsmd *g = data;
+	struct gsmd_user *newuser;
+
+	/* FIXME: implement this */
+	if (what & GSMD_FD_READ) {
+		/* new incoming connection */
+		newuser = malloc(sizeof(*newuser));
+		if (!newuser)
+			return -ENOMEM;
+		
+		newuser->gfd.fd = accept(fd, NULL, 0);
+		if (newuser->gfd.fd < 0) {
+			DEBUGP("error accepting incoming conn: `%s'\n",
+				strerror(errno));
+			free(newuser);
+		}
+		newuser->gfd.when = GSMD_FD_READ;
+		newuser->gfd.data = newuser;
+		newuser->gfd.cb = &gsmd_usock_user_cb;
+		newuser->gsmd = g;
+
+		llist_add(&newuser->list, &g->users);
+	}
+
+	return 0;
+}
+
+/* handling of socket with incoming client connections */
+int usock_init(struct gsmd *g)
+{
+	struct sockaddr_un sun;
+	int fd, rc;
+
+	fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0);
+	if (fd < 0)
+		return fd;
+	
+	sun.sun_family = AF_UNIX;
+	memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
+
+	rc = bind(fd, (struct sockaddr *)&sun, sizeof(sun));
+	if (rc < 0) {
+		close(fd);
+		return rc;
+	}
+
+	g->gfd_sock.fd = fd;
+	g->gfd_sock.when = GSMD_FD_READ | GSMD_FD_EXCEPT;
+	g->gfd_sock.data = g;
+	g->gfd_sock.cb = &gsmd_usock_cb;
+
+	return gsmd_register_fd(&g->gfd_sock);
+}

Added: trunk/src/target/gsm/src/gsmd/usock.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/usock.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/usock.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,15 @@
+#ifndef __GSMD_USOCK_H
+#define __GSMD_USOCK_H
+
+#include <gsmd/usock.h>
+
+int usock_init(struct gsmd *g);
+
+struct gsmd_ucmd {
+	struct llist_head list;
+	struct gsmd_msg_hdr hdr;
+	char buf[];
+} __attribute__ ((packed));
+
+#endif
+

Added: trunk/src/target/gsm/src/gsmd/vendor_ti.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/vendor_ti.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/vendor_ti.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,53 @@
+/* TI [Calypso] compatible backend */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "vendorplugin.h"
+
+static int 
+ti_getopt(struct gsmd *gh, int optname, void *optval, int *optlen)
+{
+	switch (optname) {
+	case GSMD_OPT_CIPHER_IND:
+		/* FIXME: send AT%CPRI=? */
+		break;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int 
+ti_setopt(struct gsmd *gh, int optname, const void *optval, int optlen)
+{
+	switch (optname) {
+	case GSMD_OPT_CIPHER_IND:
+		/* FIXME: send AT%CPRI= */
+		break;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ti_parseunsolicit(struct gsmd *gh)
+{
+	/* FIXME: parse all the below and generate the respective events */
+
+	/* %CPROAM: CPHS Home Country Roaming Indicator */
+	/* %CPVWI: CPHS Voice Message Waiting */
+	/* %CGREG: reports extended information about GPRS registration state */
+	/* %CTZV: reports network time and date information */
+	/* %CNIV: reports network name information */
+	/* %CPKY: Press Key */
+	/* %CMGRS: Message Retransmission Service */
+	/* %CGEV: reports GPRS network events */
+	return -EINVAL;
+}
+
+struct gsmd_vendorspecific ti_vendorspec = {
+	.getopt	= &ti_getopt,
+	.setopt = &ti_setopt,
+	.parse_unsolicit = &ti_parseunsolicit,
+};

Added: trunk/src/target/gsm/src/gsmd/vendorplugin.h
===================================================================
--- trunk/src/target/gsm/src/gsmd/vendorplugin.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/gsmd/vendorplugin.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,29 @@
+#ifndef __GSMD_VENDORPLUG_H
+#define __GSMD_VENDORPLUG_H
+
+#include "gsmd.h"
+
+/* gsmd vendor-specific plugin */
+
+enum gsmd_options {
+	GSMD_OPT_NONE,
+	GSMD_OPT_CIPHER_IND,
+};
+
+/* CIPHER_IND */
+enum gsmd_cipher_ind {
+	GSMD_CIPHER_IND_OFF,
+	GSMD_CIPHER_IND_ON,
+	GSMD_CIPHER_IND_SIM_FORBID,
+};
+
+struct gsmd_vendorspecific {
+	/* callback function to parse unknown unsolicited responses */	
+	int (*parse_unsolicit)(void);
+	int (*getopt)(struct gsmd *gh, int optname, void *optval, int *optlen);
+	int (*setopt)(struct gsmd *gh, int optname, const void *optval, int optlen);
+};
+
+/* ciphering indications */
+
+#endif

Added: trunk/src/target/gsm/src/libgsmd/lgsm_internals.h
===================================================================
--- trunk/src/target/gsm/src/libgsmd/lgsm_internals.h	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/libgsmd/lgsm_internals.h	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,4 @@
+
+struct lgsm_handle {
+	int fd;
+};

Added: trunk/src/target/gsm/src/libgsmd/libgsmd.c
===================================================================
--- trunk/src/target/gsm/src/libgsmd/libgsmd.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/libgsmd/libgsmd.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,69 @@
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <libgsmd/libgsmd.h>
+
+#include "lgsm_internals.h"
+
+static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)
+{
+	int rc;
+
+	if (!strcmp(device, "gsmd")) {
+		struct sockaddr_un sun;
+		
+		/* use unix domain socket to gsm daemon */
+		lh->fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0);
+		if (lh->fd < 0)
+			return lh->fd;
+		
+		sun.sun_family = AF_UNIX;
+		memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
+
+		rc = connect(lh->fd, (struct sockaddr *)&sun, sizeof(sun));
+		if (rc < 0) {
+			close(lh->fd);
+			lh->fd = -1;
+			return rc;
+		}
+	} else {
+		/* use direct access to device node ([virtual] tty device) */
+		lh->fd = open(device, O_RDWR);
+		if (lh->fd < 0)
+			return lh->fd;
+	}
+	
+	return 0;
+}
+
+struct lgsm_handle *lgsm_init(const char *device)
+{
+	struct lgsm_handle *lh = malloc(sizeof(*lh));
+
+	memset(lh, 0, sizeof(*lh));
+	lh->fd = -1;
+
+	if (lgsm_open_backend(lh, device) < 0) {
+		free(lh);
+		return NULL;
+	}
+
+	/* send some initial commands, such as ATV1 (verbose response)
+	 * and +CRC=1 (which we currently require!) */
+
+	return lh;
+}
+
+int lgsm_exit(struct lgsm_handle *lh)
+{
+	free(lh);
+
+	return 0;
+}

Added: trunk/src/target/gsm/src/libgsmd/libgsmd_input.c
===================================================================
--- trunk/src/target/gsm/src/libgsmd/libgsmd_input.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/libgsmd/libgsmd_input.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,13 @@
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include <libgsmd/libgsmd.h>
+
+#include "lgsm_internals.h"
+
+

Added: trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c
===================================================================
--- trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c	2006-08-28 06:16:17 UTC (rev 39)
+++ trunk/src/target/gsm/src/libgsmd/libgsmd_voicecall.c	2006-09-02 10:32:06 UTC (rev 40)
@@ -0,0 +1,24 @@
+
+
+#include <libgsmd/voicecall.h>
+
+#include "libgsmd/internals.h"
+
+
+int lgsm_voice_out_init(struct lgsm_handle *lh,
+			const struct lgsm_addr *number)
+{
+	/* send ATD command */
+	return -EINVAL;
+}
+
+int lgsm_voice_in_accept(struct lgsm_handle *lh)
+{
+	return -EINVAL;
+}
+
+int lgsm_voice_hangup(struct lgsm_handle *lh)
+{
+	/* Send ATH0 */
+	return -EINVAL;
+}





More information about the commitlog mailing list