SOURCES: asterisk-chan_bluetooth.patch (NEW) - added, NFY
aredridel
aredridel at pld-linux.org
Mon Nov 6 20:50:47 CET 2006
Author: aredridel Date: Mon Nov 6 19:50:47 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- added, NFY
---- Files affected:
SOURCES:
asterisk-chan_bluetooth.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/asterisk-chan_bluetooth.patch
diff -u /dev/null SOURCES/asterisk-chan_bluetooth.patch:1.1
--- /dev/null Mon Nov 6 20:50:47 2006
+++ SOURCES/asterisk-chan_bluetooth.patch Mon Nov 6 20:50:42 2006
@@ -0,0 +1,3225 @@
+diff -urN asterisk-1.4.0-beta3-o-o/build_tools/menuselect-deps.in asterisk-1.4.0-beta3/build_tools/menuselect-deps.in
+--- asterisk-1.4.0-beta3-o-o/build_tools/menuselect-deps.in 2006-09-19 11:07:22.000000000 -0600
++++ asterisk-1.4.0-beta3/build_tools/menuselect-deps.in 2006-11-06 12:45:04.000000000 -0700
+@@ -1,4 +1,5 @@
+ ASOUND=@PBX_ALSA@
++BLUETOOTH=@PBX_BLUETOOTH@
+ CURL=@PBX_CURL@
+ FREETDS=@PBX_FREETDS@
+ GSM=@PBX_GSM@
+diff -urN asterisk-1.4.0-beta3-o-o/channels/chan_bluetooth.c asterisk-1.4.0-beta3/channels/chan_bluetooth.c
+--- asterisk-1.4.0-beta3-o-o/channels/chan_bluetooth.c 1969-12-31 17:00:00.000000000 -0700
++++ asterisk-1.4.0-beta3/channels/chan_bluetooth.c 2006-11-06 12:44:39.000000000 -0700
+@@ -0,0 +1,3145 @@
++/*
++ * Asterisk -- A telephony toolkit for Linux.
++ *
++ * Asterisk Bluetooth Channel
++ *
++ * Author: Theo Zourzouvillys <theo at adaptive-it.co.uk>
++ *
++ * Adaptive Linux Solutions <http://www.adaptive-it.co.uk>
++ *
++ * Copyright (C) 2004 Adaptive Linux Solutions
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License
++ *
++ * ******************* NOTE NOTE NOTE NOTE NOTE *********************
++ *
++ * This code is not at all tested, and only been developed with a
++ * HBH-200 headset and a Nokia 6310i right now.
++ *
++ * Expect it to crash, dial random numbers, and steal all your money.
++ *
++ * PLEASE try any headsets and phones, and let me know the results,
++ * working or not, along with all debug output!
++ *
++ * ------------------------------------------------------------------
++ *
++ * Asterisk Bluetooth Support
++ *
++ * Well, here we go - Attempt to provide Handsfree profile support in
++ * both AG and HF modes, AG (AudioGateway) mode support for using
++ * headsets, and HF (Handsfree) mode for utilising mobile/cell phones
++ *
++ * It would be nice to also provide Headset support at some time in
++ * the future, however, a working Handsfree profile is nice for now,
++ * and as far as I can see, almost all new HS devices also support HF
++ *
++ * ------------------------------------------------------------------
++ * INSTRUCTIONS
++ *
++ * You need to have bluez's bluetooth stack, along with user space
++ * tools (>=v2.10), and running hcid and sdsp.
++ *
++ * See bluetooth.conf for configuration details.
++ *
++ * - Ensure bluetooth subsystem is up and running. 'hciconfig'
++ * should show interface as UP.
++ *
++ * - If you're trying to use a headset/HS, start up asterisk, and try
++ * to pair it as you normally would.
++ *
++ * - If you're trying to use a Phone/AG, just make sure bluetooth is
++ * enabled on your phone, and start up asterisk.
++ *
++ * - 'bluetooth show peers' will show all bluetooth devices states.
++ *
++ * - Send a call out by using Dial(BLT/DevName/0123456). Call a HS
++ * with Dial(BLT/DevName)
++ *
++ * ------------------------------------------------------------------
++ * BUGS
++ *
++ * - What should happen when an AG is paired with asterisk and
++ * someone uses the AG dalling a number manually? My test phone
++ * seems to try to open an SCO link. Perhaps an extension to
++ * route the call to, or maybe drop the RFCOM link all together?
++ *
++ * ------------------------------------------------------------------
++ * COMPATIBILITY
++ *
++ * PLEASE email <theo at adaptive-it.co.uk> with the results of ANY
++ * device not listed in here (working or not), or if the device is
++ * listed and it doesn't work! Please also email full debug output
++ * for any device not working correctly or generating errors in log.
++ *
++ * HandsFree Profile:
++ *
++ * HS (HeadSet):
++ * - Ericsson HBH-200
++ *
++ * AG (AudioGateway):
++ * - Nokia 6310i
++ *
++ * ------------------------------------------------------------------
++ *
++ * Questions, bugs, or (preferably) patches to:
++ *
++ * <theo at adaptive-it.co.uk>
++ *
++ * ------------------------------------------------------------------
++ */
++
++/*! \file
++ *
++ * \brief Channel driver for Bluetooth phones and headsets
++ *
++ * \author Theo Zourzouvillys <theo at adaptive-it.co.uk>
++ *
++ * \par See also
++ * \arg \ref Config_bluetooth
++ *
++ * \ingroup channel_drivers
++ */
++
++
++/*** MODULEINFO
++ <depend>bluetooth</depend>
++ ***/
++
++
++/* ---------------------------------- */
++
++#include <stdio.h>
++#include <string.h>
++#include <asterisk/lock.h>
++#include <asterisk/utils.h>
++#include <asterisk/channel.h>
++#include <asterisk/channel_pvt.h>
++#include <asterisk/config.h>
++#include <asterisk/logger.h>
++#include <asterisk/module.h>
++#include <asterisk/pbx.h>
++#include <asterisk/sched.h>
++#include <asterisk/options.h>
++#include <asterisk/cli.h>
++#include <asterisk/callerid.h>
++#include <sys/socket.h>
++#include <sys/signal.h>
++#include <sys/time.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <arpa/inet.h>
++#include <fcntl.h>
++#include <sys/ioctl.h>
++#include <ctype.h>
++
++#include <bluetooth/bluetooth.h>
++#include <bluetooth/hci.h>
++#include <bluetooth/hci_lib.h>
++#include <bluetooth/sco.h>
++#include <bluetooth/rfcomm.h>
++#include <bluetooth/sdp.h>
++#include <bluetooth/sdp_lib.h>
++
++/* --- Data types and definitions --- */
++
++#ifndef HANDSFREE_AUDIO_GW_SVCLASS_ID
++# define HANDSFREE_AUDIO_GW_SVCLASS_ID 0x111f
++#endif
++
++#define BLUETOOTH_FORMAT AST_FORMAT_SLINEAR
++#define BLT_CHAN_NAME "BLT"
++#define BLT_CONFIG_FILE "bluetooth.conf"
++#define BLT_RDBUFF_MAX 1024
++#define BLT_DEFAULT_HCI_DEV 0
++#define BLT_SVN_REVISION "$Rev: 38 $"
++
++/* ---------------------------------- */
++
++typedef enum {
++ BLT_ROLE_NONE = 0, // Unknown Device
++ BLT_ROLE_HS = 1, // Device is a Headset
++ BLT_ROLE_AG = 2 // Device is an Audio Gateway
++} blt_role_t;
++
++/* State when we're in HS mode */
++
++typedef enum {
++ BLT_STATE_WANT_R = 0,
++ BLT_STATE_WANT_N = 1,
++ BLT_STATE_WANT_CMD = 2,
++ BLT_STATE_WANT_N2 = 3,
++} blt_state_t;
++
++typedef enum {
++ BLT_STATUS_DOWN,
++ BLT_STATUS_CONNECTING,
++ BLT_STATUS_NEGOTIATING,
++ BLT_STATUS_READY,
++ BLT_STATUS_RINGING,
++ BLT_STATUS_IN_CALL,
++} blt_status_t;
++
++/* ---------------------------------- */
++
++/* Default config settings */
++
++#define BLT_DEFAULT_CHANNEL_AG 5
++#define BLT_DEFAULT_CHANNEL_HS 6
++#define BLT_DEFAULT_ROLE BLT_ROLE_HS
++#define BLT_OBUF_LEN (48 * 25)
++
++#define BUFLEN 4800
++
++/* ---------------------------------- */
++
++typedef struct blt_dev blt_dev_t;
++
++// XXX:T: Tidy this lot up.
++struct blt_dev {
++
++ blt_status_t status; /* Device Status */
++
++ struct ast_channel * owner; /* Channel we belong to, possibly NULL */
++ blt_dev_t * dev; /* The bluetooth device channel is for */
++ struct ast_frame fr; /* Recieved frame */
++
++ /* SCO Handler */
++ int sco_pipe[2]; /* SCO alert pipe */
++ int sco; /* SCO fd */
++ int sco_handle; /* SCO Handle */
++ int sco_mtu; /* SCO MTU */
++ int sco_running; /* 1 when sCO thread should be running */
++ pthread_t sco_thread; /* SCO thread */
++ ast_mutex_t sco_lock; /* SCO lock */
++ int sco_pos_in; /* Reader in position */
++ int sco_pos_out; /* Reader out position */
++ int sco_sending; /* Sending SCO packets */
++ char buf[1024]; /* Incoming data buffer */
++ char sco_buf_out[BUFLEN+1]; /* 24 chunks of 48 */
++ char sco_buf_in[BUFLEN+1]; /* 24 chunks of 48 */
++
++ char dnid[1024]; /* Outgoi gncall dialed number */
++ unsigned char * obuf[BLT_OBUF_LEN]; /* Outgoing data buffer */
++ int obuf_len; /* Output Buffer Position */
++ int obuf_wpos; /* Buffer Reader */
++
++ // device
++ int autoconnect; /* 1 for autoconnect */
++ int outgoing_id; /* Outgoing connection scheduler id */
++ char * name; /* Devices friendly name */
++ blt_role_t role; /* Device role (HS or AG) */
++ bdaddr_t bdaddr; /* remote address */
++ int channel; /* remote channel */
++ int rd; /* RFCOMM fd */
++ int tmp_rd; /* RFCOMM fd */
++ int call_cnt; /* Number of attempted calls */
++ ast_mutex_t lock; /* RFCOMM socket lock */
++ char rd_buff[BLT_RDBUFF_MAX]; /* RFCOMM input buffer */
++ int rd_buff_pos; /* RFCOMM input buffer position */
++ int ready; /* 1 When ready */
++
++ /* AG mode */
++ char last_ok_cmd[BLT_RDBUFF_MAX]; /* Runtime[AG]: Last AT command that was OK */
++ int cind; /* Runtime[AG]: Recieved +CIND */
++ int call_pos, service_pos, callsetup_pos; /* Runtime[AG]: Positions in CIND/CMER */
++ int call, service, callsetup; /* Runtime[AG]: Values */
++
++ /* HS mode */
++ blt_state_t state; /* Runtime: Device state (AG mode only) */
++ int ring_timer; /* Runtime:Ring Timer */
++ char last_err_cmd[BLT_RDBUFF_MAX]; /* Runtime: Last AT command that was OK */
++ void (*cb)(blt_dev_t * dev, char * str); /* Runtime: Callback when in HS mode */
++
++ int brsf; /* Runtime: Bluetooth Retrieve Supported Features */
++ int bvra; /* Runtime: Bluetooth Voice Recognised Activation */
++ int gain_speaker; /* Runtime: Gain Of Speaker */
++ int clip; /* Runtime: Supports CLID */
++ int colp; /* Runtime: Connected Line ID */
++ int elip; /* Runtime: (Ericsson) Supports CLID */
++ int eolp; /* Runtime: (Ericsson) Connected Line ID */
++ int ringing; /* Runtime: Device is ringing */
++
++ blt_dev_t * next; /* Next in linked list */
++
++};
++
++typedef struct blt_atcb {
++
++ /* The command */
++ char * str;
++
++ /* DTE callbacks: */
++ int (*set)(blt_dev_t * dev, const char * arg, int len);
++ int (*read)(blt_dev_t * dev);
++ int (*execute)(blt_dev_t * dev, const char * data);
++ int (*test)(blt_dev_t * dev);
++
++ /* DCE callbacks: */
++ int (*unsolicited)(blt_dev_t * dev, const char * value);
++
++} blt_atcb_t;
++
++/* ---------------------------------- */
++
++static void rd_close(blt_dev_t * dev, int reconnect, int err);
++static int send_atcmd(blt_dev_t * device, const char * fmt, ...);
++static int sco_connect(blt_dev_t * dev);
++
++/* ---------------------------------- */
++
++/* RFCOMM channel we listen on*/
++static int rfcomm_channel_ag = BLT_DEFAULT_CHANNEL_AG;
++static int rfcomm_channel_hs = BLT_DEFAULT_CHANNEL_HS;
++
++/* Address of local bluetooth interface */
++static int hcidev_id;
++static bdaddr_t local_bdaddr;
++
++/* All the current sockets */
++AST_MUTEX_DEFINE_STATIC(iface_lock);
++static blt_dev_t * iface_head;
++static int ifcount = 0;
++
++static int sdp_record_hs = -1;
++static int sdp_record_ag = -1;
++
++/* RFCOMM listen socket */
++static int rfcomm_sock_ag = -1;
++static int rfcomm_sock_hs = -1;
++static int sco_socket = -1;
++
++static int monitor_pid = -1;
++
++/* The socket monitoring thread */
++static pthread_t monitor_thread = AST_PTHREADT_NULL;
++AST_MUTEX_DEFINE_STATIC(monitor_lock);
++
++/* Cound how many times this module is currently in use */
++static int usecnt = 0;
++AST_MUTEX_DEFINE_STATIC(usecnt_lock);
++
++static struct sched_context * sched = NULL;
++
++/* ---------------------------------- */
++
++static const char *
++role2str(blt_role_t role)
++{
++ switch (role) {
++ case BLT_ROLE_HS:
++ return "HS";
++ case BLT_ROLE_AG:
++ return "AG";
++ case BLT_ROLE_NONE:
++ return "??";
++ }
++}
++
++static const char *
++status2str(blt_status_t status)
++{
++ switch (status) {
++ case BLT_STATUS_DOWN:
++ return "Down";
++ case BLT_STATUS_CONNECTING:
++ return "Connecting";
++ case BLT_STATUS_NEGOTIATING:
++ return "Negotiating";
++ case BLT_STATUS_READY:
++ return "Ready";
++ case BLT_STATUS_RINGING:
++ return "Ringing";
++ case BLT_STATUS_IN_CALL:
++ return "InCall";
++ };
++ return "Unknown";
++}
++
++int sock_err(int fd)
++{
++ int ret;
++ int len = sizeof(ret);
++ getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
++ return ret;
++}
++
++/* ---------------------------------- */
++
++static const char *
++parse_cind(const char * str, char * name, int name_len)
++{
++ int c = 0;
++
++ memset(name, 0, name_len);
++
++ while (*str) {
++ if (*str == '(') {
++ if (++c == 1 && *(str+1) == '"') {
++ const char * start = str + 2;
++ int len = 0;
++ str += 2;
++ while (*str && *str != '"') {
++ len++;
++ str++;
++ }
++ if (len == 0)
++ return NULL;
++ strncpy(name, start, (len > name_len) ? name_len : len);
++ }
++ } else if (*str == ')')
++ c--;
++ else if (c == 0 && *str == ',')
++ return str + 1;
++ str++;
++ }
++ return NULL;
++}
++
++static void
++set_cind(blt_dev_t * dev, int indicator, int val)
++{
++
++ ast_log(LOG_DEBUG, "CIND %d set to %d\n", indicator, val);
++
++ if (indicator == dev->callsetup_pos) {
++
++ // call progress
++
++ dev->callsetup = val;
++
++ switch (val) {
++ case 3:
++ // Outgoign ringing
++ if (dev->owner && dev->role == BLT_ROLE_AG)
++ ast_queue_control(dev->owner, AST_CONTROL_RINGING);
++ break;
++ case 2:
++ break;
++ case 1:
++ break;
++ case 0:
++ if (dev->owner && dev->role == BLT_ROLE_AG && dev->call == 0)
++ ast_queue_control(dev->owner, AST_CONTROL_CONGESTION);
++ break;
++ }
++
++ } else if (indicator == dev->service_pos) {
++
++ // Signal
++
++ if (val == 0)
++ ast_log(LOG_NOTICE, "Audio Gateway %s lost signal\n", dev->name);
++ else if (dev->service == 0 && val > 0)
++ ast_log(LOG_NOTICE, "Audio Gateway %s got signal\n", dev->name);
++
++ dev->service = val;
++
++ } else if (indicator == dev->call_pos) {
++
++ // Call
++
++ dev->call = val;
++
++ if (dev->owner) {
++ if (val == 1) {
++ ast_queue_control(dev->owner, AST_CONTROL_ANSWER);
++ } else if (val == 0)
++ ast_queue_control(dev->owner, AST_CONTROL_HANGUP);
++ }
++
++ }
++
++
++}
++
++/* ---------------------------------- */
++
++int
++set_buffer(char * ring, char * data, int circular_len, int * pos, int data_len)
++{
++ int start_pos = *(pos);
++ int done = 0;
++ int copy;
++
++ while (data_len) {
++ // Set can_do to the most we can do in this copy.
++
++ copy = MIN(circular_len - start_pos, data_len);
++ memcpy(ring + start_pos, data + done, copy);
++
++ done += copy;
++ start_pos += copy;
++ data_len -= copy;
++
++ if (start_pos == circular_len)
++ start_pos = 0;
++ }
++ *(pos) = start_pos;
++ return 0;
++}
++
++int
++get_buffer(char * dst, char * ring, int ring_size, int * head, int to_copy)
++{
++ int copy;
++
++ // |1|2|3|4|5|6|7|8|9|
++ // |-----|
++
++ while (to_copy) {
++
++ // Set can_do to the most we can do in this copy.
++ copy = MIN(ring_size - *head, to_copy);
++
++ // ast_log(LOG_DEBUG, "Getting: %d bytes, From pos %d\n", copy, *head);
++ memcpy(dst, ring + *head, copy);
++
++ dst += copy;
++ *head += copy;
++ to_copy -= copy;
++
++ if (*head == ring_size )
++ *head = 0;
++
++ }
++
++ return 0;
++}
++
++/* Handle SCO audio sync.
++ *
++ * If we are the MASTER, then we control the timing,
++ * in 48 byte chunks. If we're the SLAVE, we send
++ * as and when we recieve a packet.
++ *
++ * Because of packet/timing nessecity, we
++ * start up a thread when we're passing audio, so
++ * that things are timed exactly right.
++ *
++ * sco_thread() is the function that handles it.
++ *
++ */
++
++static void *
++sco_thread(void * data)
++{
++ blt_dev_t * dev = (blt_dev_t*)data;
++ int res;
++ struct pollfd pfd[2];
++ int in_pos = 0;
++ int out_pos = 0;
++ char c = 1;
++ int sending;
++ char buf[1024];
++ int len;
++
++ // Avoid deadlock in odd circumstances
++
++ ast_log(LOG_DEBUG, "SCO thread started on fd %d, pid %d\n", dev->sco, getpid());
++
++ // dev->status = BLT_STATUS_IN_CALL;
++ // ast_queue_control(dev->owner, AST_CONTROL_ANSWER);
++ // Set buffer to silence, just incase.
++
++ ast_mutex_lock(&(dev->sco_lock));
++
++ memset(dev->sco_buf_in, 0x7f, BUFLEN);
++ memset(dev->sco_buf_out, 0x7f, BUFLEN);
++
++ dev->sco_pos_in = 0;
++ dev->sco_pos_out = 0;
++
++ ast_mutex_unlock(&(dev->sco_lock));
++
++ while (1) {
++
++ ast_mutex_lock(&(dev->sco_lock));
++
++ if (dev->sco_running != 1) {
++ ast_log(LOG_DEBUG, "SCO stopped.\n");
++ break;
++ }
++
++ pfd[0].fd = dev->sco;
++ pfd[0].events = POLLIN;
++
++ pfd[1].fd = dev->sco_pipe[1];
++ pfd[1].events = POLLIN;
++
++ ast_mutex_unlock(&(dev->sco_lock));
++
++ res = poll(pfd, 2, 50);
++
++ if (res == -1 && errno != EINTR) {
++ ast_log(LOG_DEBUG, "SCO poll() error\n");
++ break;
++ }
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list