97干视频,99国产精品懂色,亚洲精品99久久久久中文字幕,伊人五月丁香综合AⅤ,国产精品成人免费999

  您的位置:華清遠(yuǎn)見教育科技集團(tuán) >> 新聞動(dòng)態(tài) >> Android資料 >> SMD 數(shù)據(jù)通信的實(shí)現(xiàn)  
 
SMD 數(shù)據(jù)通信的實(shí)現(xiàn)
分享到:

在《Android SMD數(shù)據(jù)通信概述》一文中,我們了解到基于SMD的數(shù)據(jù)通信是以信道的形式作為一個(gè)設(shè)備存在的,作為一種雙向信道,其接口的實(shí)現(xiàn)遵循Linux設(shè)備驅(qū)動(dòng)規(guī)范。本文會(huì)結(jié)合SMD信道的實(shí)現(xiàn)簡(jiǎn)要介紹SMD信道的分配、打開、讀取、寫入、關(guān)閉等操作。

1.分配信道

SMD信道根據(jù)數(shù)據(jù)的類型可以分為流信道和包信道,其中包信道具有比流信道更強(qiáng)的流控制能力,包含頭信息。在創(chuàng)建SMD信道時(shí),會(huì)根據(jù)信道類型的不同,確定創(chuàng)建的是FIFO信道還是普通信道,是流信道還是包信道,然后為SMD進(jìn)行設(shè)備注冊(cè)。SMD分配信道的實(shí)現(xiàn)如下:

代碼1-1 SMD分配信道的過程

static void smd_alloc_channel(struct smd_alloc_elm *alloc_elm)
    {
        struct smd_channel *ch;
        uint32_t *smd_ver;
        //分配SMEM內(nèi)存
        smd_ver=smem_alloc(SMEM_VERSION_SMD, 32 * sizeof(uint32_t));
        if (smd_ver && ((smd_ver[VERSION_MODEM]>>16)>=1))
            ch=smd_alloc_channel_v2(alloc_elm->cid); //FIFO信道
        else
            ch=smd_alloc_channel_v1(alloc_elm->cid); //普通信道
        if (ch==0)
            return;
        ch->type=SMD_CHANNEL_TYPE(alloc_elm->type);
        memcpy(ch->name, alloc_elm->name, 20);
        ch->name[19]=0;
        if (smd_is_packet(alloc_elm)) { //包信道
            ch->read=smd_packet_read;
            ch->write=smd_packet_write;
            ch->read_avail=smd_packet_read_avail;
            ch->write_avail=smd_packet_write_avail;
            ch->update_state=update_packet_state;
            ch->read_from_cb=smd_packet_read_from_cb;
        } else { //流信道
            ch->read=smd_stream_read;
            ch->write=smd_stream_write;
            ch->read_avail=smd_stream_read_avail;
            ch->write_avail=smd_stream_write_avail;
            ch->update_state=update_stream_state;
            ch->read_from_cb=smd_stream_read;
        }
        ch->pdev.name=ch->name;
        ch->pdev.id=ch->type;
        pr_info("smd_alloc_channel() '%s' cid=%d\n",ch->name, ch->n);
        mutex_lock(&smd_creation_mutex); //互斥鎖
        //將信道添加到“smd_ch_closed_list”列表中
        list_add(&ch->ch_list, &smd_ch_closed_list); mutex_unlock(&smd_creation_mutex);
        platform_device_register(&ch->pdev); //注冊(cè)設(shè)備
    }

2.打開信道

為了打開一個(gè)信道,首先要判斷SMD信道是否已經(jīng)初始化。如果SMD信道已經(jīng)初始化,就根據(jù)信道名獲得信道,將信道加入到“smd_ch_list”信道列表中并設(shè)置該信道的狀態(tài)為SMD_SS_OPENING,然后調(diào)用notify_other_smd()函數(shù)通知其他的信道該信道已經(jīng)激活。在默認(rèn)情況下,其信道類型為SMD_APPS_MODEM,打開一個(gè)SMD信道的實(shí)現(xiàn)如下:

代碼1-2 SMD打開信道的過程

int smd_named_open_on_edge(const char *name, uint32_t edge,smd_channel_t **_ch,void *priv, void (*notify)(void *, unsigned))
    {
        struct smd_channel *ch;
        unsigned long flags;
        if (smd_initialized==0) { //判斷SMD信道是否已初始化
            printk(KERN_INFO "smd_open() before smd_init()\n");
            return -ENODEV;
        }
        D("smd_open('%s', %p, %p)\n", name, priv, notify);
        ch=smd_get_channel(name, edge); //獲取信道
        if (!ch)
            return -ENODEV;
        if (notify==0)
            notify=do_nothing_notify;
        ch->notify=notify;
        ch->current_packet=0;
        ch->last_state=SMD_SS_CLOSED;
        ch->priv=priv;
        *_ch=ch;
        D("smd_open: opening '%s'\n", ch->name);
        spin_lock_irqsave(&smd_lock, flags); //自旋鎖
        list_add(&ch->ch_list, &smd_ch_list); //將信道添加到“smd_ch_list”列表中
        D("%s: opening ch %d\n", __func__, ch->n);
        smd_state_change(ch, ch->last_state, SMD_SS_OPENING); //信道狀態(tài)變更
        spin_unlock_irqrestore(&smd_lock, flags);
        return 0;
    }

3.關(guān)閉信道

關(guān)閉信道的操作相對(duì)簡(jiǎn)單,首先將信道從“smd_ch_list”信道列表中刪除,然后將信道狀態(tài)設(shè)置為SMD_SS_CLOSED,并將信道添加到“smd_ch_closed_list”信道列表中即可。關(guān)閉SMD信道的實(shí)現(xiàn)如下:

代碼1-3 SMD關(guān)閉信道的過程

int smd_close(smd_channel_t *ch)
    {
        unsigned long flags;
        printk(KERN_INFO "smd_close(%p)\n", ch);
        if (ch==0)
            return -1;
        spin_lock_irqsave(&smd_lock, flags); //自旋鎖
        ch->notify=do_nothing_notify;
        list_del(&ch->ch_list); //從打開信道列表中去除該信道
        ch_set_state(ch, SMD_SS_CLOSED); //設(shè)置信道狀態(tài)
        spin_unlock_irqrestore(&smd_lock, flags);
        mutex_lock(&smd_creation_mutex); //互斥鎖
        list_add(&ch->ch_list, &smd_ch_closed_list); //將信道添加至關(guān)閉信道列表
        mutex_unlock(&smd_creation_mutex);
        return 0;
    }

4.信道讀取

包信道的內(nèi)容讀取涉及緩沖的復(fù)制、與其他SMD的消息通信和包狀態(tài)的更新。從包信道讀取數(shù)據(jù)的實(shí)現(xiàn)如下:

代碼1-4 SMD包信道讀取數(shù)據(jù)的過程

static int smd_packet_read(smd_channel_t *ch, void *data, int len)
    {
        unsigned long flags;
        int r;
        if (len< 0)
            return -EINVAL;
        if (len>ch->current_packet)
            len=ch->current_packet;
        r=ch_read(ch, data, len); //讀取數(shù)據(jù)
        if (r>0)
            notify_other_smd(ch->type);
        spin_lock_irqsave(&smd_lock, flags); //自旋鎖
        ch->current_packet-=r;
        update_packet_state(ch); //更新包狀態(tài)
        spin_unlock_irqrestore(&smd_lock, flags);
        return r;
    }

流信道的內(nèi)容讀取非常簡(jiǎn)單,只需要調(diào)用ch_read()函數(shù)讀取數(shù)據(jù)并通知其他SMD該信道處于打開狀態(tài)即可。流信道讀取的實(shí)現(xiàn)如下:

代碼1-5 SMD流信道讀取數(shù)據(jù)的過程

static int smd_stream_read(smd_channel_t *ch, void *data, int len)
    {
        int r;
        if (len< 0)
            return -EINVAL;
        r=ch_read(ch, data, len); //讀取數(shù)據(jù)
        if (r>0)
            notify_other_smd(ch->type); //通知其他SMD,該信道處于激活狀態(tài)。
        return r;
    }

流信道和包信道在讀取信道數(shù)據(jù)時(shí),都需要調(diào)用ch_read()函數(shù)來實(shí)現(xiàn)真正的數(shù)據(jù)讀取,ch_read()函數(shù)的實(shí)現(xiàn)如下:

代碼1-6 SMD信道讀取數(shù)據(jù)的過程

static int ch_read(struct smd_channel *ch, void *_data, int len)
    {
        void *ptr;
        unsigned n;
        unsigned char *data=data;
        int orig_len=len;
        while (len>0) {
            n=ch_read_buffer(ch, &ptr); //讀取緩沖
            if (n==0)
                break;
            if (n>len)
                n=len;
            if (data)
                memcpy(data, ptr, n); //數(shù)據(jù)復(fù)制
            data+=n;
            len-=n;
            ch_read_done(ch,n); //讀取完成
        }
        return orig_len-len;
    }

5.信道寫入

在信道的數(shù)據(jù)寫入方面,同樣分為流信道數(shù)據(jù)的寫入和包信道數(shù)據(jù)的寫入兩種類型。

向包信道中寫入數(shù)據(jù)的過程和讀取數(shù)據(jù)不同,在寫入數(shù)據(jù)前,要首先利用smd_stream_write_avail()函數(shù)判斷是否有數(shù)據(jù)可供寫入,在確定有可供寫入的數(shù)據(jù)的情況下才調(diào)用smd_stream_write()函數(shù)執(zhí)行數(shù)據(jù)的寫入操作。包信道寫入數(shù)據(jù)的實(shí)現(xiàn)如下:

代碼1-7 SMD包信道寫入數(shù)據(jù)的過程

static int smd_packet_write(smd_channel_t *ch, const void *_data, int len)
    {
        int ret;
        unsigned hdr[5];
        D("smd_packet_write() %d->ch%d\n",len, ch->n);
        if (len< 0)
            return-EINVAL;
        if (smd_stream_write_avail(ch)<(len+SMD_HEADER_SIZE)) //判斷數(shù)據(jù)寫入進(jìn)度
            return-ENOMEM;
        hdr[0]=len;
        hdr[1]=hdr[2]=hdr[3]=hdr[4]=0;
        ret=smd_stream_write(ch, hdr, sizeof(hdr)); //流寫入
        if (ret< 0 || ret!=sizeof(hdr)) {
            D("%s failed to write pkt header: ""%d returned\n", __func__, ret);
            return -1;
        }
        ret=smd_stream_write(ch, _data, len);
        if (ret< 0 || ret != len) {
            D("%s failed to write pkt data: ""%d returned\n", __func__, ret);
            return ret;
        }
        return len;
    }

流信道數(shù)據(jù)的寫入和包信道數(shù)據(jù)的寫入不同,其首先獲得下一段可用緩沖的指針,然后執(zhí)行內(nèi)存復(fù)制,流信道寫入數(shù)據(jù)的實(shí)現(xiàn)如下:

代碼1-8 SMD流信道寫入數(shù)據(jù)的過程

static int smd_stream_write(smd_channel_t *ch, const void *_data, int len)
    {
        void *ptr;
        const unsigned char *buf=data;
        unsigned xfer;
        int orig_len=len;
        D("smd_stream_write() %d->ch%d\n", len, ch->n);
        if (len< 0)
            return -EINVAL;
        while ((xfer=ch_write_buffer(ch, &ptr)) != 0) //寫入數(shù)據(jù)
        {
            if (!ch_is_open(ch))
                break;
            if (xfer>len)
                xfer=len;
            memcpy(ptr, buf, xfer); //內(nèi)存復(fù)制
            ch_write_done(ch, xfer); //完成寫入數(shù)據(jù)
            len-=xfer;
            buf+=xfer;
            if (len==0)
                break;
        }
        if (orig_len-len)
            notify_other_smd(ch->type); //通知其他SMD,該信道處于激活狀態(tài)
        return orig_len-len;
    }

SMD是多核通信的基礎(chǔ),在SMD之上是一個(gè)叫做RPC路由器(RPC Router)的封裝。關(guān)于RPC路由器,將在3.2節(jié)過程調(diào)用中詳細(xì)介紹。

通過SMD,可以為系統(tǒng)提供RPC、DIAG、AT命令、NMEA(GPS數(shù)據(jù))、數(shù)據(jù)服務(wù)、撥號(hào)等服務(wù)。

 更多相關(guān)文章

·Android SMD數(shù)據(jù)通信概述
·淺析Android多媒體元數(shù)據(jù)
·Android Stagefright多媒體框架
·Android PVPlayer引擎A/V同步技術(shù)
·Android OSCL底層移植