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 @@ + [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ + [EMAIL PROTECTED]@ + [EMAIL PROTECTED]@ + [EMAIL PROTECTED]@ +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 <[EMAIL PROTECTED]> ++ * ++ * 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 <[EMAIL PROTECTED]> 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: ++ * ++ * <[EMAIL PROTECTED]> ++ * ++ * ------------------------------------------------------------------ ++ */ ++ ++/*! \file ++ * ++ * \brief Channel driver for Bluetooth phones and headsets ++ * ++ * \author Theo Zourzouvillys <[EMAIL PROTECTED]> ++ * ++ * \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>> _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
