免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 837 | 回复: 0
打印 上一主题 下一主题

writing-an-alsa-driver(编写一个ALSA驱动)翻译稿 第三章 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-20 13:54 |只看该作者 |倒序浏览

       
       
翻译:creator

sz111@126.com

第三章
管理card和组件
card实例
    对于每个声卡,都要分配一个card记录。
   
一个card记录相当于一个声卡的总部。它管理着声卡中的所有设备(组件),例如PCM,mixers,MIDI,音序器等等。同时,card记录还保持着卡的ID和name字符串,管理proc文件,控制电源管理状态和热拔插。[color="#800000"]Card[color="#800000"]的组件列表用来在合适的时候释放资源。
   
[color="#000000"]如上,为了创建一个card[color="#000000"]实例,需要调用snd_card_new().
[color="#800000"]   
Struct
snd_card *card;
    card
= snd_card_new(index, id, module, extra_size);     
   
这个函数需要4[color="#000000"]个参数,card-index[color="#000000"]号,id[color="#000000"]字符串,module[color="#000000"]指针(通常是THIS_MODULE),extra-data[color="#000000"]空间的大小。最后一个参数是用来分配chip-specific[color="#000000"]数据card->private_data[color="#000000"]的。注意这个数据是通过snd_card_new()[color="#000000"]进行分配。
[color="#000000"]组件
   
card[color="#000000"]被创建之后,你可以把组件(设备)附加到card[color="#000000"]实例上面。在ALSA驱动
程序中,一个组件用一个snd_devie[color="#000000"]结构体表示。可以是PCM[color="#000000"],控制接口或raw
MIDI[color="#000000"]接口等等。每个组件都有个入口函数。
   
通过snd_device_new()[color="#000000"]函数来创建组件。
   
snd_device_new(card,
SNDRV_DEV_XXX, chip, &ops);
   
它需要card[color="#000000"]指针,device_level[color="#000000"](SNDRV_DEV_XXX),[color="#000000"]数据指针和回调函数(&ops)[color="#000000"]。device-level定义了组件类型和注册和卸载的顺序。对于大部分的组件来说,
device_level[color="#000000"]已经定义好了。对于用户自定义的组件,你可以用SNDRV_DEV_LOWLEVEL.
   
这个函数自己并不分配数据空间。数据必须提前分配,同时把分配好的数据指针传递给这个函数作为参数。这个指针可以作为设备实例的标识符(上述代码的chip[color="#000000"])。
   
每个ALSA[color="#000000"]预定义组件,如ac97[color="#000000"]或pcm[color="#000000"]都是通过在各自的构造函数中调用snd_device_new().[color="#000000"]在一些回调函数中定义了每个组件的析构函数。因此,你不需要关心这种组件的析构函数的调用。
   
假如你要创建一个自己的组件,你需要在dev_free[color="#000000"]中的回调函数ops[color="#000000"]中设定析构函数。
[color="#000000"]以便它可以通过snd_card_free()[color="#000000"]自动被释放。下面的例子就会显示chip-specific[color="#000000"]数据的实现。
Chip-Specific
Data
   
chip-specific[color="#000000"]信息,如:i/o口,资源,或者中断号就会保持在
chip-specific[color="#000000"]记录里面。
    Struct
mychip{
[color="#000000"]        ....
[color="#000000"]    };
   
通常来说,有两种方式来分配chip[color="#000000"]记录。
   
1.[color="#000000"]通过snd_card_new()[color="#000000"]分配。
     
如上面所述,你可以通过传递extra-data-length[color="#000000"]到snd_card_new()[color="#000000"]的第四个参数。
      card
= snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct
mychip));
[color="#000000"]      无论struct
mychip[color="#000000"]是否是chip[color="#000000"]记录类型。
     
分配之后,可以通过如下方式引用:
          struct
mychip *chip = char->private_data;
   

     
通过这种方法,你不必分配两次。这个记录将会和card[color="#000000"]实例一起被释放。
[color="#000000"]   
[color="#000000"]     2.[color="#000000"]分配一个extra
device[color="#000000"]。
      
当你通过snd_card_new()([color="#000000"]第四个参数要设定为NULL)[color="#000000"]分配之后,通过调用kzalloc().
       Struct
snd_card *card;
       struct
mychip *chip;
       card
= snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
[color="#000000"]       ....
       chip
= kzalloc(sizeof(*chip), GFP_KERNEL);
      
chip[color="#000000"]记录应该至少拥有一个snd_card[color="#000000"]指针的成员变量。
       Struct
mychip {
            
struct
snd_card *card;
            
....
[color="#000000"]       };
      
然后,设定chip[color="#000000"]的card[color="#000000"]为snd_card_new[color="#000000"]返回的card[color="#000000"]指针。
         
chip->card
= card;
      
下一步,初始化各个成员变量,使用一个含有特殊的ops[color="#000000"]的low-level[color="#000000"]设备注册chip[color="#000000"]记录。
       Static
struct snd_device_ops ops = {
         
.dev_free =
snd_mychip_dev_free;
[color="#000000"]       };
[color="#000000"]       ....
      
snd_device_new(card,
SNDRV_DEV_LOWLEVEL, chip, &ops);
   

      
snd_mychip_dev_free()[color="#000000"]是作为设备的析构函数会调用真正的析构函数调用。
[color="#000000"]
       static
int snd_mychip_dev_free(struct snd_device *device)
[color="#000000"]       {
           return
snd_mychip_free(device->private_data);
[color="#000000"]        }
        
snd_mychip_free[color="#000000"]是真正的设备析构函数。
[color="#000000"]注册和释放
   
当所有的组件都被分配之后,就可以通过snd_card_register()[color="#000000"]来注册card[color="#000000"]实例了。对于设备文件的操作也会使能。那是因为,在调用snd_card_register()[color="#000000"]调用之前,组件是不能被外界调用的。假如注册失败,必须要调用snd_card_free()[color="#000000"]来释放card[color="#000000"]。
   
对于释放card[color="#000000"],你可以简单的通过snd_card_free().[color="#000000"]如前所述,所有的组件都可以通过它来自动释放。
   
要特别注意,这些析构函数(包括snd_mychip_dev_free[color="#000000"]和snd_mychip_free)[color="#000000"]不能被定义加入__devexit[color="#000000"]前缀,因为它们也有可能被构造函数调用(当构造失败的时候调用)。
   
对于一个运行热拔插的设备,你可以用snd_card_free_when_closed。
它将推迟析构直到所有的设备都关闭。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/49088/showart_1006027.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP