亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? writing-an-alsa-driver.tmpl

?? 優龍2410linux2.6.8內核源代碼
?? TMPL
?? 第 1 頁 / 共 5 頁
字號:
        id string, the module pointer (usually        <constant>THIS_MODULE</constant>),        and the size of extra-data space.  The last argument is used to        allocate card-&gt;private_data for the        chip-specific data.  Note that this data        <emphasis>is</emphasis> allocated by        <function>snd_card_new()</function>.      </para>    </section>    <section id="card-management-component">      <title>Components</title>      <para>        After the card is created, you can attach the components      (devices) to the card instance. On ALSA driver, a component is      represented as a <type>snd_device_t</type> object.      A component can be a PCM instance, a control interface, a raw      MIDI interface, etc.  Each of such instances has one component      entry.      </para>      <para>        A component can be created via        <function>snd_device_new()</function> function.         <informalexample>          <programlisting><![CDATA[  snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);]]>          </programlisting>        </informalexample>      </para>      <para>        This takes the card pointer, the device-level      (<constant>SNDRV_DEV_XXX</constant>), the data pointer, and the      callback pointers (<parameter>&amp;ops</parameter>). The      device-level defines the type of components and the order of      registration and de-registration.  For most of components, the      device-level is already defined.  For a user-defined component,      you can use <constant>SNDRV_DEV_LOWLEVEL</constant>.      </para>      <para>      This function itself doesn't allocate the data space. The data      must be allocated manually beforehand, and its pointer is passed      as the argument. This pointer is used as the identifier      (<parameter>chip</parameter> in the above example) for the      instance.       </para>      <para>        Each ALSA pre-defined component such as ac97 or pcm calls      <function>snd_device_new()</function> inside its      constructor. The destructor for each component is defined in the      callback pointers.  Hence, you don't need to take care of      calling a destructor for such a component.      </para>      <para>        If you would like to create your own component, you need to      set the destructor function to dev_free callback in      <parameter>ops</parameter>, so that it can be released      automatically via <function>snd_card_free()</function>. The      example will be shown later as an implementation of a      chip-specific data.       </para>    </section>    <section id="card-management-chip-specific">      <title>Chip-Specific Data</title>      <para>      The chip-specific information, e.g. the i/o port address, its      resource pointer, or the irq number, is stored in the      chip-specific record.      Usually, the chip-specific record is typedef'ed as      <type>xxx_t</type> like the following:        <informalexample>          <programlisting><![CDATA[  typedef struct snd_mychip mychip_t;  struct snd_mychip {          ....  };]]>          </programlisting>        </informalexample>      </para>      <para>        You might have objections against such a typedef, but this      typedef is necessary if you use a <quote>magic-cast</quote>      (explained <link      linkend="card-management-chip-what-advantage"><citetitle>later</citetitle></link>).       </para>      <para>        In general, there are two ways to allocate the chip record.      </para>      <section id="card-management-chip-specific-snd-card-new">        <title>1. Allocating via <function>snd_card_new()</function>.</title>        <para>          As mentioned above, you can pass the extra-data-length to the 4th argument of <function>snd_card_new()</function>, i.e.          <informalexample>            <programlisting><![CDATA[  card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(mychip_t));]]>            </programlisting>          </informalexample>          whether <type>mychip_t</type> is the type of the chip record.        </para>        <para>          In return, the allocated record can be accessed as          <informalexample>            <programlisting><![CDATA[  mychip_t *chip = (mychip_t *)card->private_data;]]>            </programlisting>          </informalexample>          With this method, you don't have to allocate twice. But you        cannot use <quote>magic-cast</quote> for this record pointer,        instead.         </para>      </section>      <section id="card-management-chip-specific-allocate-extra">        <title>2. Allocating an extra device.</title>        <para>          After allocating a card instance via          <function>snd_card_new()</function> (with          <constant>NULL</constant> on the 4th arg), call          <function>snd_magic_kcalloc()</function>.           <informalexample>            <programlisting><![CDATA[  snd_card_t *card;  mychip_t *chip;  card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);  .....  chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);]]>            </programlisting>          </informalexample>          Once when the record is allocated via snd_magic stuff, you        can use <quote>magic-cast</quote> for the void pointer.         </para>        <para>          The chip record should have the field to hold the card          pointer at least,           <informalexample>            <programlisting><![CDATA[  struct snd_mychip {          snd_card_t *card;          ....  };]]>            </programlisting>          </informalexample>        </para>        <para>          Then, set the card pointer in the returned chip instance.          <informalexample>            <programlisting><![CDATA[  chip->card = card;]]>            </programlisting>          </informalexample>        </para>        <para>          Also, you need to define a magic-value for <type>mychip_t</type>.          <informalexample>            <programlisting><![CDATA[  #define mychip_t_magic        0xa15a4501]]>            </programlisting>          </informalexample>	(the detail will be described in the	<link linkend="card-management-chip-what-advantage"><citetitle>	next</citetitle></link> subsection).	</para>        <para>          Next, initialize the fields, and register this chip          record as a low-level device with a specified          <parameter>ops</parameter>,           <informalexample>            <programlisting><![CDATA[  static snd_device_ops_t ops = {          .dev_free =        snd_mychip_dev_free,  };  ....  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);]]>            </programlisting>          </informalexample>          <function>snd_mychip_dev_free()</function> is the        device-destructor function, which will call the real        destructor.         </para>        <para>          <informalexample>            <programlisting><![CDATA[  static int snd_mychip_dev_free(snd_device_t *device)  {          mychip_t *chip = snd_magic_cast(mychip_t, device->device_data,                                          return -ENXIO);          return snd_mychip_free(chip);  }]]>            </programlisting>          </informalexample>          where <function>snd_mychip_free()</function> is the real destructor.        </para>      </section>      <section id="card-management-chip-what-advantage">        <title>Not a magic but a logic</title>        <para>Now, you might have a question: What is the advantage of the        second method?  Obviously, it looks far more complicated.</para>         <para>          As I wrote many times, the second method allows a        <quote>magic-cast</quote> for <type>mychip_t</type>. If you        have a void pointer (such as        pcm-&gt;private_data), the pointer type        is unknown at the compile time, and you cannot know even if a        wrong pointer type is passed. The compiler would accept        it. The magic-cast checks the pointer type at the runtime (and        whether it's a null pointer, too). Hence, the cast will be        much safer and good for debugging.         </para>	<para>	As you have already seen, allocation with a magic-header can	be done via <function>snd_magic_kmalloc()</function> or	<function>snd_magic_kcalloc()</function>.          <informalexample>            <programlisting><![CDATA[  mychip_t *chip;  chip = snd_magic_kmalloc(mychip_t, 0, GFP_KERNEL);  chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);]]>            </programlisting>          </informalexample>        The difference of these two functions is whether the area is	zero-cleared (<function>kcalloc</function>) or not	(<function>kmalloc</function>).	</para>	<para>	The first argument of the allocator is the type of the	record.  The magic-constant has to be defined for this type	beforehand.  In this case, we'll need to define	<constant>mychip_t_magic</constant>, for example, as already	seen,          <informalexample>            <programlisting><![CDATA[  #define mychip_t_magic        0xa15a4501]]>            </programlisting>          </informalexample>        The value is arbitrary but should be unique.        This is usually defined in        <filename>&lt;include/sndmagic.h&gt;</filename> or        <filename>&lt;include/amagic.h&gt;</filename> for alsa-driver tree,        but you may define it locally in the code at the early        development stage, since changing        <filename>sndmagic.h</filename> will lead to the recompilation        of the whole driver codes.        </para>	<para>	The second argument is the extra-data length.  It is usually        zero.  The third argument is the flags to be passed to kernel        memory allocator, <constant>GFP_XXX</constant>.  Normally,        <constant>GFP_KERNEL</constant> is passed.	</para>        <para>          For casting a pointer, use          <function>snd_magic_cast()</function> macro:          <informalexample>            <programlisting><![CDATA[  mychip_t *chip = snd_magic_cast(mychip_t, source_pointer, action);]]>            </programlisting>          </informalexample>        where <parameter>source_pointer</parameter> is the pointer to        be casted (e.g. pcm-&gt;private_data), and        <parameter>action</parameter> is the action to do if the cast        fails (e.g. return <constant>-EINVAL</constant>).         </para>	<para>	For releasing the magic-allocated data, you need to call        <function>snd_magic_kfree()</function> function instead of        <function>kfree()</function>.          <informalexample>            <programlisting><![CDATA[  snd_magic_kfree(chip);]]>            </programlisting>          </informalexample>	</para>	<para>	If you call <function>kfree()</function> for the	magic-allocated value, it will lead to memory leaks.	When the ALSA drivers are compiled with	<constant>CONFIG_SND_DEBUG_MEMORY</constant> kernel config (or	configured with <option>--with-debug=full</option>), the	non-matching free will be checked and you'll see warning	messages.	</para>        <para>          If you are 100% sure that your code is bug-free, you can          compile the driver without          <constant>CONFIG_SND_DEBUG_MEMORY</constant> kernel config,          so that the magic-allocator and the magic-cast will be          replaced to the normal kmalloc and cast.        </para>      </section>    </section>    <section id="card-management-registration">      <title>Registration and Release</title>      <para>        After all components are assigned, register the card instance      by calling <function>snd_card_register()</function>. The access      to the device files are enabled at this point. That is, before      <function>snd_card_register()</function> is called, the      components are safely inaccessible from external side. If this      call fails, exit the probe function after releasing the card via      <function>snd_card_free()</function>.       </para>      <para>        For releasing the card instance, you can call simply      <function>snd_card_free()</function>. As already mentioned, all      components are released automatically by this call.       </para>      <para>        As further notes, the destructors (both      <function>snd_mychip_dev_free</function> and      <function>snd_mychip_free</function>) cannot be defined with      <parameter>__devexit</parameter> prefix, because they may be      called from the constructor, too, at the false path.       </para>      <para>      For a device which allows hotplugging, you can use      <function>snd_card_free_in_thread</function>.  This one will      postpone the destruction and wait in a kernel-thread until all      devices are closed.      </para>    </section>  </chapter><!-- ****************************************************** --><!-- PCI Resource Managements  --><!-- ****************************************************** -->  <chapter id="pci-resource">    <title>PCI Resource Managements</title>

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
91黄色免费网站| 99在线热播精品免费| 国产精品久久久久久久久久久免费看 | 欧美国产日韩精品免费观看| 欧美三级蜜桃2在线观看| 日韩二区在线观看| 亚洲男人天堂一区| 日本一区二区免费在线观看视频 | 精品国产凹凸成av人网站| 91浏览器在线视频| 波多野结衣在线aⅴ中文字幕不卡| 日韩精品亚洲一区二区三区免费| 曰韩精品一区二区| 欧美国产成人精品| 国产精品三级视频| 精品剧情在线观看| 日韩欧美国产小视频| 欧美一级二级在线观看| 粉嫩av一区二区三区| 韩国成人在线视频| 久久99精品久久久久久动态图| 中文字幕制服丝袜一区二区三区| 久久女同性恋中文字幕| 精品国产91乱码一区二区三区 | 欧美视频在线观看一区二区| 成人app网站| 国产精品资源在线观看| 国产一区二区不卡| 国产精品一区一区| 丁香五精品蜜臀久久久久99网站| 国产福利一区二区三区视频在线 | 精品毛片乱码1区2区3区| 9i看片成人免费高清| 波波电影院一区二区三区| 99精品视频在线播放观看| 日本不卡视频一二三区| 午夜私人影院久久久久| 蜜臀精品久久久久久蜜臀| 日韩精品电影一区亚洲| 日韩电影在线免费| 国产一区久久久| 毛片不卡一区二区| 国产美女一区二区三区| 国产99精品在线观看| av一二三不卡影片| 欧美三级视频在线| 精品久久国产老人久久综合| 国产亚洲1区2区3区| 欧美一卡二卡在线| 国产精品乱人伦| 亚洲欧洲精品一区二区三区不卡| 亚洲欧美在线视频观看| 亚洲一区二区精品视频| 日本欧美久久久久免费播放网| 另类欧美日韩国产在线| 色综合天天综合色综合av| 精品福利av导航| 亚洲成在人线免费| 91麻豆文化传媒在线观看| 久久精品一区二区三区四区| 免费成人你懂的| 制服丝袜av成人在线看| 亚洲自拍偷拍麻豆| 色先锋资源久久综合| 国产精品美女久久久久av爽李琼| 久热成人在线视频| 欧美一区二区人人喊爽| 午夜欧美大尺度福利影院在线看| eeuss鲁片一区二区三区 | 国产一区在线视频| 日韩无一区二区| 另类小说视频一区二区| 日韩欧美在线123| 日韩激情一二三区| 3atv一区二区三区| 日韩高清在线观看| 日韩美女视频一区二区在线观看| 亚洲v中文字幕| 成人听书哪个软件好| 久久免费精品国产久精品久久久久 | 亚洲精品久久嫩草网站秘色| 99久久精品国产一区二区三区| 国产精品毛片高清在线完整版| 国产成人在线免费| 国产欧美一区二区精品仙草咪| 国产乱人伦精品一区二区在线观看| 精品精品欲导航| 国产福利不卡视频| 亚洲男同性视频| 欧美日韩国产123区| 日韩av不卡在线观看| 777午夜精品免费视频| 六月丁香综合在线视频| 久久久综合精品| caoporen国产精品视频| 亚洲黄色片在线观看| 欧美日韩精品欧美日韩精品一 | 国产精品狼人久久影院观看方式| 成人黄页在线观看| 一区二区三区加勒比av| 欧美一级午夜免费电影| 国产成人在线视频免费播放| 亚洲色图欧美偷拍| 欧美一级高清大全免费观看| 国产激情偷乱视频一区二区三区 | 亚洲mv在线观看| 精品国内片67194| aa级大片欧美| 蜜桃精品视频在线观看| 欧美激情一区二区三区四区| 在线精品视频一区二区三四| 蜜桃av一区二区三区电影| 国产精品麻豆久久久| 91精品国产欧美一区二区18 | 午夜欧美电影在线观看| 欧美精品一区二区久久婷婷| 成人一区二区三区在线观看| 亚洲高清视频的网址| 2023国产精品自拍| 欧美网站一区二区| 夫妻av一区二区| 首页综合国产亚洲丝袜| 国产亚洲一区二区三区在线观看| 成人一级黄色片| 蜜臀av性久久久久蜜臀aⅴ流畅| 国产精品欧美一级免费| 欧美日韩一区二区不卡| 国产盗摄女厕一区二区三区| 亚洲一区在线免费观看| 欧美国产国产综合| 精品国产一区二区精华| 欧美色手机在线观看| 成人精品高清在线| 久久97超碰国产精品超碰| 亚洲电影你懂得| 亚洲视频小说图片| 亚洲国产精华液网站w| 欧美r级电影在线观看| 欧美日韩激情一区二区三区| 99re视频精品| 国产成人免费视频一区| 美腿丝袜在线亚洲一区| 一区二区在线观看视频在线观看| 欧美国产日韩精品免费观看| 精品国产91久久久久久久妲己| 欧美三级在线看| 欧美亚洲动漫制服丝袜| 91麻豆国产在线观看| 成人91在线观看| 99久久婷婷国产| 91在线精品一区二区| 成人免费高清在线观看| 国产精品一区二区免费不卡| 久久超级碰视频| 精油按摩中文字幕久久| 蜜桃一区二区三区在线| 日本免费在线视频不卡一不卡二| 调教+趴+乳夹+国产+精品| 亚洲v日本v欧美v久久精品| 亚洲大片在线观看| 视频一区二区中文字幕| 免费观看在线综合| 国产麻豆精品久久一二三| 国产精品18久久久久久vr| 成人夜色视频网站在线观看| 不卡视频一二三| 91在线观看污| 欧美日本一道本在线视频| 日韩一区二区三区四区| 久久众筹精品私拍模特| 欧美激情在线看| 一区二区三区不卡视频| 视频在线观看91| 国产一区视频在线看| 丁香激情综合国产| 91激情五月电影| 日韩亚洲欧美成人一区| 久久香蕉国产线看观看99| 国产拍欧美日韩视频二区| 亚洲欧美偷拍另类a∨色屁股| 亚洲电影视频在线| 激情偷乱视频一区二区三区| 岛国精品在线观看| 欧美影视一区二区三区| 日韩欧美国产电影| 国产精品国产三级国产aⅴ原创| 夜夜精品视频一区二区| 麻豆一区二区在线| 色婷婷精品久久二区二区蜜臂av | 69堂亚洲精品首页| 久久婷婷国产综合国色天香| 国产日韩精品一区二区浪潮av| 日韩理论在线观看| 青草国产精品久久久久久| 成人免费视频caoporn| 欧美乱妇一区二区三区不卡视频| 亚洲精品一区二区三区四区高清| 国产精品系列在线| 一区二区三区在线免费观看| 另类欧美日韩国产在线|