Chinaunix首页 | 论坛 | 博客
  • 博客访问: 446495
  • 博文数量: 78
  • 博客积分: 2030
  • 博客等级: 大尉
  • 技术积分: 1002
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-28 15:25
文章分类

全部博文(78)

文章存档

2012年(1)

2011年(1)

2010年(4)

2009年(12)

2008年(60)

我的朋友

分类: LINUX

2008-10-30 18:07:23

自己写的简单的实验代码,贴上来看看,有兴趣的话,大家可以交流
/******************************************************************************/
/**                                                                                                                           **/
/**                         MODULES USED                                                                  **/
/**                                                                                                                            **/
/******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "msgqueue.h"
/******************************************************************************/
/**                                                                                                                           **/
/**                         DEFINITIONS AND MACROS                                              **/
/**                                                                                                                           **/
/******************************************************************************/
#define DONGLE_ADDR  "00:11:67:58:D1:0F"     /*ISSC*/
#define HEAD_SET_ADDR "83:82:5B:00:A5:A3"     /*NK-808 channel 1*/
#define HEAD_SET_CHAN   1

//#define PCM_DATA_PATH   "/tmp/sco.dat"
//#define PCM_DATA_PATH   "/mnt/heart.pcm"
#define PCM_DATA_PATH   "/mnt/tianhou.pcm"

#define RECV_BUFFER     64
#define SEND_BUFFER     64

typedef pthread_t thread_T;
typedef void *(*pthread_startroutine_t) (void *);
typedef void *pthread_addr_t;
typedef void threadArg_T;
typedef void (*threadFunc_T)(void *);

/*debugging micro*/
#ifdef ENABLE_DEBUG
int DebugEnabled = 0;
#else
#define DebugEnabled    1
#endif
#define DDBG(fmts)  if(DebugEnabled)printf(fmts)
#define DBG(fmts,args) if(DebugEnabled)printf(fmts,args)
#define DBG2(fmts,arg1,arg2) if(DebugEnabled)printf(fmts,arg1,arg2)
/******************************************************************************/
/**                                                                                                                           **/
/**                            TYPEDEF AND STRUCTURE                                          **/
/**                                                                                                                            **/
/******************************************************************************/
struct _dongle_priv {
    int hci_sock;
    int sco_sock;
    int device_channel;
    char ag_addr[20];  /* adddress of adapter */
    char hs_addr[20];
    unsigned char isServiceConnected;
    char isScoConnected;
    char isRunning;
    char callSetup;
    char callAccept; 

};
typedef struct _dongle_priv bt_data;
/******************************************************************************/
/**                                                                                                                           **/
/**                            GLOBAL VARIABLES                                                         **/
/**                                                                                                                            **/
/******************************************************************************/
bt_data * BTd;
static sem_t   Sem;
/******************************************************************************/
/**                                                                                                                           **/
/**                         LOCAL FUNCTIONS                                                             **/
/**                                                                                                                            **/
/******************************************************************************/
thread_T thread_create(int priority, threadFunc_T startFunc, threadArg_T *arg)
{
    thread_T             thread;
    pthread_attr_t       thread_attr;
    struct sched_param   param;

    pthread_attr_init(&thread_attr);
    /* pthread_attr_setinheritsched(PTHREAD_EXPLICT_SCHED); */
    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);

    param.sched_priority = priority;
    pthread_attr_setschedparam(&thread_attr, ¶m);

    pthread_create(&thread, &thread_attr, (pthread_startroutine_t)startFunc,
                   (pthread_addr_t)arg);
    return(thread);
}

void set_bit(int offset)
{
    BTd->isServiceConnected |= (0x01<}


static int rfcomm_connect(bdaddr_t * src, bdaddr_t * dst, uint8_t channel)
{
 struct sockaddr_rc addr;
 int s;

 if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
  return -1;
 }

 memset(&addr, 0, sizeof(addr));
 addr.rc_family = AF_BLUETOOTH;
 bacpy(&addr.rc_bdaddr, src);
 addr.rc_channel = 0;
 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  printf("rfcomm bind error\n");
  close(s);
  return -1;
 }

 memset(&addr, 0, sizeof(addr));
 addr.rc_family = AF_BLUETOOTH;
 bacpy(&addr.rc_bdaddr, dst);
 addr.rc_channel = channel;
 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  printf("rfcomm connect error\n");
  close(s);
  return -1;
 } else{
  printf("connecting successfully sock %d\n",s);
 }

 return s;
}

static int sco_connect(bdaddr_t *src, bdaddr_t *dst)
{

 struct sockaddr_sco addr;
 //struct sco_conninfo conn;
 //struct sco_options opts;
 int s;

 if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
  return -1;
  }
 memset(&addr, 0, sizeof(addr));
 addr.sco_family = AF_BLUETOOTH;
 bacpy(&addr.sco_bdaddr, src);
 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  close(s);
  return -1;
  }
 memset(&addr, 0, sizeof(addr));
 addr.sco_family = AF_BLUETOOTH;
 bacpy(&addr.sco_bdaddr, dst);
 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
  close(s);
  printf("sco connecting failed\n");
  return -1;
  }

 return s;
}

static int start_rfcomm_link(char *dst , char *src , int channel)
{
    bdaddr_t usb_dongle_addr,head_set_addr; 
    int fd;
   
    if (!dst||!src){
        return -1;
    }

    str2ba(src,&usb_dongle_addr);
 str2ba(dst,&head_set_addr);
 
    fd = rfcomm_connect(&usb_dongle_addr,&head_set_addr,channel);

    return fd;

}

static int start_sco_link(char *dst , char *src)
{
    bdaddr_t usb_dongle_addr,head_set_addr; 
    int fd;

    //uint16_t sco_handle, sco_mtu;

   
    if (!dst||!src){
        return -1;
    }

    str2ba(src,&usb_dongle_addr);
 str2ba(dst,&head_set_addr);
 
    fd = sco_connect(&usb_dongle_addr,&head_set_addr);

    return fd;

}

static int cind_cmd_str(char *cmd)
{
    if (!cmd){
        return -1;
    }

    memset(cmd,0,sizeof(cmd));
    strcpy(cmd,"\r\n+CIND:(\"service\",(0,1)),(\"call\",(0,1)),(\"callsetup\",(0,3)),(\"signal\",(0-5)),(\"roam\",(0-1))\r\n");
    return 0;
          
}

static int at_rx(int fd_at, char *receive)
{
    int retval,ret;
    fd_set rfds;
 struct timeval tv;

 FD_ZERO(&rfds);
 FD_SET(fd_at, &rfds);
 tv.tv_sec = 0;
 tv.tv_usec = 5000;
   

    if (!receive){
        return -1;
    }

    memset(receive,0,sizeof(receive));

 if ((retval = select(fd_at+1, &rfds, NULL, NULL, &tv)) > 0){ 
     memset(receive,0,RECV_BUFFER);
  ret = read(fd_at,receive,RECV_BUFFER);
        if (ret > 0){
            DBG("recving from headset %s\n",receive);
           
        } else if (-1 == ret){
            close(fd_at);
            BTd->isRunning = 0;
        }
 } else if (!retval){
     //DDBG("time out\n");
 }
    
 return 0;   
   
}

static int at_tx(int fd_at,char* send)

 if (strlen(send)){
     DBG("AG Sending %s\n",send);
     write(fd_at,send,strlen(send));
 }

    
 return 0;
}

static int at_txrx(int fd_at,char* send, char *receive)

 int ret = 0;
 fd_set rfds;
 struct timeval tv;
 int retval;
   
 FD_ZERO(&rfds);
 FD_SET(fd_at, &rfds);
 tv.tv_sec = 3;
 tv.tv_usec = 0;

 memset(receive,0,sizeof(receive));

 if (strlen(send)){
     DBG("AG Sending %s\n",send);
     write(fd_at,send,strlen(send));
 }

 if ((retval = select(fd_at+1, &rfds, NULL, NULL, &tv)) > 0){ 
     memset(receive,0,RECV_BUFFER);
  ret = read(fd_at,receive,RECV_BUFFER);
        if (ret){
            DBG("[at_rxtx]recving from headset %s\n",receive);
        }
 } else if (!retval){
     //DDBG("time out\n");
 }
    
 return 0;
}

static void monitor_headset(int fd_rfcomm)
{
    char recv_buf[RECV_BUFFER] = {0};
    char send_buf[SEND_BUFFER] = {0};

   
    while (1 == BTd->isRunning){
        at_rx(fd_rfcomm, recv_buf);

        if (strstr(recv_buf,"AT+BRSF")){
            at_tx(fd_rfcomm,"\r\n+BRSF:49\r");
            at_tx(fd_rfcomm,"\r\nOK\r\n");
            set_bit(0);
            continue;
        }

        if (strstr(recv_buf,"AT+CIND=?")){
            cind_cmd_str(send_buf);
            at_tx(fd_rfcomm,send_buf);
            at_tx(fd_rfcomm,"\r\nOK\r\n");
            set_bit(1);
            continue;
        }

        if (strstr(recv_buf,"AT+CIND")){
            at_tx(fd_rfcomm,"\r\n+CIND:1,0,0,2,0\r\n");
            at_tx(fd_rfcomm,"\r\nOK\r\n");   
            set_bit(2);
            continue;
        }

        if (strstr(recv_buf,"AT+CMER")){
            at_tx(fd_rfcomm,"\r\nOK\r\n");   
            set_bit(3);
            continue;
        }
        //Standard call hold and multiparty handling AT command
        if (strstr(recv_buf,"AT+CHLD")){
            at_tx(fd_rfcomm,"\r\n+CHLD:0\r\n");           
            at_tx(fd_rfcomm,"\r\nOK\r\n");
            set_bit(4);
            continue;
        }
        //Standard “Call Waiting notification” AT command
        if (strstr(recv_buf,"AT+CCWA")){
            at_tx(fd_rfcomm,"\r\nOK\r\n");   
            set_bit(5);
            continue;
        }
        //volume setting
        if (strstr(recv_buf,"AT+VGS")){      
            at_tx(fd_rfcomm,"\r\nOK\r\n");   
            set_bit(6);
            continue;           
        }
        //volume setting
        if (strstr(recv_buf,"AT+VGM")){        
            at_tx(fd_rfcomm,"\r\nOK\r\n");  
            set_bit(7);
            continue;           
        }

        if (strstr(recv_buf,"ATA")){
            //CallingAccept = 1;
            BTd->callAccept = 1;
            DDBG("ATA is received\n");
            at_tx(fd_rfcomm,"\r\nOK\r\n"); 
            at_tx(fd_rfcomm,"\r\n+CIEV=2,1\r\n");   
            continue;

        }
       
    }  
}

static void audio_loop(int fd_sco)
{   
    char recv_buf[RECV_BUFFER] = {0};
    int retval,ret;
    fd_set rfds;
 struct timeval tv;

 FD_ZERO(&rfds);
 FD_SET(fd_sco, &rfds);
 tv.tv_sec = 3;
 tv.tv_usec = 0;
 memset(recv_buf,0,RECV_BUFFER);
 if ((retval = select(fd_sco+1, &rfds, NULL, NULL, &tv)) > 0){ 
  ret = read(fd_sco,recv_buf,1023);
        if (ret){
            //DBG("recving from headset %s\n",receive);
            //DBG("recv_length %d\n",ret);
            //DBG("%x\n",recv_buf);           
        }
        write(fd_sco,recv_buf,ret);
 } else if (!retval){
     //DDBG("time out\n");
 }
}

static int get_file_size(char *file_path)
{
    FILE * fd;
    int start,end,fileLen;

    fd = fopen(file_path,"r");

    if (fd){   
        fseek(fd, 0, SEEK_SET);
     start = ftell(fd);
     fseek(fd, 0, SEEK_END);
     end = ftell(fd);
     fileLen = end - start + 1;
     /*move to the head*/
        fseek(fd, 0, SEEK_SET);
     DBG("audio fileLength %d\n",fileLen);
     fclose(fd);
     return fileLen;
 } else{
     return -1;
 }

}

static unsigned char * fill_pcm_buffer(char * pcm_file_path,int *length)
{
    int size = 0;
    FILE *fd;
    unsigned char * pcmDataPtr;

    if (!pcm_file_path){
        return NULL;
    }

    size = get_file_size(pcm_file_path);
   
    if (size > 0){
        *length = size;
        pcmDataPtr = (unsigned char *)malloc(size);
        if (!pcmDataPtr){
            DDBG("can't allocate memory\n");
            return NULL;
        }
        memset(pcmDataPtr,0,size);
        fd = fopen(pcm_file_path,"r");
        if (!fd){
            return NULL;
        }

        fread(pcmDataPtr,1,size,fd);
        fclose(fd);
        return pcmDataPtr;
    } else{
        return NULL;
    }
   
}

static bt_data * init_bt_para()
{
    bt_data * btd;
    btd = (bt_data *)malloc(sizeof(bt_data));
    if (!btd){
        printf("opps can't allocate resource!\n");
        exit(-1);
    }

    memset(btd,0,sizeof(*btd));

    strcpy(btd->ag_addr,DONGLE_ADDR);
    strcpy(btd->hs_addr,HEAD_SET_ADDR);

    btd->device_channel = HEAD_SET_CHAN;

    btd->callSetup = 0;
    btd->callAccept = 0;
    btd->isRunning = 0;
    btd->isServiceConnected = 0;
    btd->isScoConnected = 0;
   
    btd->hci_sock = -1;
    btd->sco_sock = -1;

    return btd;           
   
}

static int ring_headset(int fd_rfcomm)
{
    char recv_buf[RECV_BUFFER] = {0};


    sem_wait(&Sem);

    at_txrx(fd_rfcomm,"\r\nRING\r\n",recv_buf);
    while (!strstr(recv_buf,"ATA")&&!BTd->callAccept){
        at_txrx(fd_rfcomm,"\r\nRING\r\n",recv_buf);           
    }
    at_tx(fd_rfcomm,"\r\nOK\r\n");           

    at_tx(fd_rfcomm,"\r\n+CIEV:2,1\r\n");  
    sem_destroy(&Sem);

    return 0;  
   
}


static void play_pcm_audio(int fd_sco,unsigned char * pcm_buffer,int max_length,int times)
{
#define OFFSET  48
    int i;
    int cur = 0;
    int retval;
    unsigned char *pdata;
    unsigned char buffer[64];
    fd_set rfds,wfds;   
 struct timeval tv;
    unsigned int sector = 300*1024;

 if (!pcm_buffer){
     return -1;
 }

    FD_ZERO(&rfds);
 FD_SET(fd_sco, &rfds);
 FD_ZERO(&wfds);
 FD_SET(fd_sco, &wfds);

 tv.tv_sec = 0;
 tv.tv_usec =8000;

    pdata = pcm_buffer;
    
    for (i = 0 ; i < times ; i++){
        while (cur < max_length){
         if ((retval = select(fd_sco+1, NULL, &wfds, NULL, &tv)) > 0){         
                //fread(receive,1,OFFSET,fd_music);
                //memset(buffer,0,sizeof(buffer));
                //memcpy(buffer,pdata,OFFSET);
                printf("twins\r\n");
                //printf("twins\r\n");
                //usleep(1);
                //printf("\r\n");
                write(fd_sco,pdata,48);
                cur += OFFSET;
                pdata += OFFSET;     
                if (cur > sector){
                    sleep(5);
                    sector += 300*1024;
                }
            }
        }
        printf("music data is finished\n");
        sleep(2);
       
        pdata = pcm_buffer;
        cur = 0;
        sector = 300*1024;
   }
        //close(fd_sco);
    free(pcm_buffer);
    printf("audio transfer over\n");
    return;

}

void init_hcid_conf()
{
    system("hcid -f /etc/bluetooth/hcid.conf");
}

int main()
{
    int fd_rfcomm,fd_sco;
    unsigned char * pcm_buffer;
    int max_length;

    bt_data *btd;
    init_hcid_conf();

    btd = init_bt_para();
    BTd = btd;


    fd_rfcomm = start_rfcomm_link(btd->hs_addr, btd->ag_addr, btd->device_channel);
   
    if (fd_rfcomm < 0){           
        exit(-1);
    }
    btd->isRunning = 1;

    btd->hci_sock = fd_rfcomm;
    thread_create(50, (threadFunc_T)monitor_headset, (threadArg_T *)btd->hci_sock);
    thread_create(50, (threadFunc_T)ring_headset, (threadArg_T *)btd->hci_sock);
    pcm_buffer = fill_pcm_buffer(PCM_DATA_PATH, &max_length);

    while (1){
        if (btd->isServiceConnected == 0xff&&!btd->callSetup){
            //printf("service level connection finished\n");
            //ready to make/accept a call
            at_tx(fd_rfcomm,"\r\n+CIEV=3,1\r\n");   
            sem_post(&Sem);
            //CallSetup = 1;
            btd->callSetup = 1;
        }   

        if (0 == btd->isScoConnected){
            fd_sco = start_sco_link(btd->hs_addr,btd->ag_addr);
        }

        if (fd_sco > 0){
            //printf("sco link successfully!\n");
            btd->sco_sock = fd_sco;
            btd->isScoConnected = 1;
        }
   
        if (btd->callAccept == 1){

            play_pcm_audio(btd->sco_sock, pcm_buffer, max_length,1);
            break;
        }
    }
    //sleep(80);
    close(btd->sco_sock);
    close(btd->hci_sock);
}

阅读(5598) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~