14. AC 97 디바이스 드라이버

Post on 15-Jan-2016

48 views 0 download

description

14. AC 97 디바이스 드라이버. 목차. 14.1 Sound 용 Codec chip architecture 14.1.1 CS4202 14.1.2 AC’97 Controller Unit 14.2 Sound Device Driver 의 원리 14.3 Audio 구동 13.3.1 Mixer 13.3.2 madplayer 14.4 OSS(Open Sound System) Interface 를 이용한 Sound Programming. 14.1.1 CS4202. - PowerPoint PPT Presentation

Transcript of 14. AC 97 디바이스 드라이버

14. AC 97 14. AC 97 디바이스 드라이버디바이스 드라이버

www.huins.com 2

목차목차14.1 Sound 용 Codec chip architecture

14.1.1 CS4202

14.1.2 AC’97 Controller Unit

14.2 Sound Device Driver 의 원리

14.3 Audio 구동13.3.1 Mixer

13.3.2 madplayer

14.4 OSS(Open Sound System) Interface 를 이용한 Sound Programming

www.huins.com 3

14.1.1 CS420214.1.1 CS4202

www.huins.com 4

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit AC-Link

www.huins.com 5

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Audio Frame

www.huins.com 6

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit AC-link Audio Output Frame(SDATA_OUT)

A new audio output frame begins with a low-to-high SYNC transition synchronous to BITCLK’s rising edge. BITCLK’s falling edge immediately follows and AC’97 samples SYNC’s assertion.

BITCLK’s falling edge marks the instance that AC-link’s sides are each aware that a new audio frame has started. On BITCLK’s next rising edge, the ACUNIT transitions SDATA_OUT into the slot 0’s first bit position (valid frame bit). Each new bit position is presented to AC-link on a BITCLK rising edge and then sampled by AC’97 on the following BITCLK falling edge. This sequence ensures that data transitions and subsequent sample points for both incoming and outgoing data streams are time aligned.

www.huins.com 7

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Start of Audio Output Frame

www.huins.com 8

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit AC-link Audio Input Frame (SDATA_IN)

www.huins.com 9

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Start of an Audio Input Frame

www.huins.com 10

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Feature List

The processor ACUNIT supports the following AC’97 features: Independent channels for Stereo PCM In, Stereo PCM out, modem-out, mode

m-in and mono mic-in. All of the above channels support only 16-bit samples in hardware. Samples l

ess than 16 bits are supported through software.

www.huins.com 11

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit

www.huins.com 12

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Signal Configuration Steps

1. Configure SYNC and SDATA_OUT as outputs.

2. Configure BITCLK, SDATA_IN_0, and SDATA_IN_1 as inputs.

3. nACRESET is a dedicated output. It remains asserted on power-up. Complete these steps to deassert nACRESET:

a. Configure the other AC’97 signals as previously described.

b. In the Global Control Register(GCR), Set the GCR[COLD_RST]bit.

www.huins.com 13

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Signal Configuration Steps(Cont’)

www.huins.com 14

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Waking up the AC-link

www.huins.com 15

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Waking up the AC-link(Cont’)

To wake up the AC-link, a CODEC drives SDATA_IN to a logic high level. The rising edge triggers the Resume Interrupt if that CODEC’s resume enable bit is set to a one.

The CPU then wakes up the CODEC using the cold or warm reset se

quence. The ACUNIT uses a warm reset to wake up the primary CODEC. The CODEC detects a warm reset when SYNC is driven high for a minimum of one microsecond and the BITCLK is absent.

The CODEC must wait until it samples SYNC low before it can start BITCLK. The CODEC that signaled the wake event must keep its SDATA_IN high until it detects that a warm reset has been completed. The CODEC can then transition its SDATA_IN low.

www.huins.com 16

14.1.2 AC’97 Controller Unit14.1.2 AC’97 Controller Unit Codec Access Register

www.huins.com 17

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석

static u16 pxa_ac97_read(struct ac97_codec *codec, u8 reg){

u16 val = -1;

down(&CAR_mutex);if (!(CAR & CAR_CAIP)) {

volatile u32 *reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);

waitingForMask=GSR_SDONE;

init_completion(&CAR_completion); //start read access across the ac97 link(void)*reg_addr;

wait_for_completion(&CAR_completion);

0x40500200 : primary audio codec

1 << 18

done = 0 wait = null

www.huins.com 18

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

Each CODEC has up to sixty-four 16-bit registers that are addressable internal to the CODEC at half-word boundaries(16-bit boundaries). Because the processor only supports internal register accesses at word boundaries (32-bit boundaries), software must select the one of the following formulas to translate a 7-bit CODEC address into a 32-bit processor address:

Processor physical address for a Primary Audio CODEC = 0x4050-0200 + Shift_Left_Once(Internal 7-bit CODEC Register Address)

Processor physical address for a Secondary Audio CODEC = 0x4050-0300 + Shift_Left_Once(Internal 7-bit CODEC Register Address)

Processor physical address for a Primary Modem CODEC = 0x4050-0400 + Shift_Left_Once(Internal 7-bit CODEC Register Address)

Processor physical address for a Secondary Modem CODEC = 0x4050-0500 + Shift_Left_Once(Internal 7-bit CODEC Register Address)

www.huins.com 19

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 Global Status Register(GSR)

www.huins.com 20

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

if (GSR & GSR_RDCS) {GSR |= GSR_RDCS;printk(KERN_CRIT __FUNCTION__": read

codec register timeout.\n");}

init_completion(&CAR_completion);val = *reg_addr;

wait_for_completion(&CAR_completion);

} else {printk(KERN_CRIT __FUNCTION__": CAR_CAIP

already set\n");}up(&CAR_mutex);return val;

}

cleared by software writing a ‘1’ to this location

www.huins.com 21

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

static void pxa_ac97_write(struct ac97_codec *codec, u8 reg, u16 val){

down(&CAR_mutex);if (!(CAR & CAR_CAIP)) {

volatile u32 *reg_addr= (u32 *)&PAC_REG_BASE + reg >>1);

waitingForMask=GSR_CDONE;init_completion(&CAR_completion);*reg_addr = val;wait_for_completion(&CAR_completion);

} else {printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");

}up(&CAR_mutex);

}

0x40500200 : primary audio codec

1 << 19

www.huins.com 22

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

static void pxa_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)

{

int gsr = GSR;

GSR = gsr & (GSR_SDONE|GSR_CDONE);

if (gsr & waitingForMask)

{

complete(&CAR_completion);

}

}

0x4050001C

GSCI = 1

www.huins.com 23

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

static struct ac97_codec pxa_ac97_codec = {

codec_read: pxa_ac97_read,

codec_write: pxa_ac97_write,

};

static DECLARE_MUTEX(pxa_ac97_mutex);

static int pxa_ac97_refcount;

www.huins.com 24

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

int pxa_ac97_get(struct ac97_codec **codec)

{

int ret;

*codec = NULL;

down(&pxa_ac97_mutex);

if (!pxa_ac97_refcount) {

ret = request_irq(IRQ_AC97, pxa_ac97_irq, 0, "AC97", NULL);

if (ret)

return ret;

www.huins.com 25

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

CKEN |= CKEN2_AC97;

set_GPIO_mode(GPIO31_SYNC_AC97_MD);

set_GPIO_mode(GPIO30_SDATA_OUT_AC97_MD);

set_GPIO_mode(GPIO28_BITCLK_AC97_MD);

set_GPIO_mode(GPIO29_SDATA_IN_AC97_MD);

GCR = 0;

udelay(10);

GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE;

while (!(GSR & GSR_PCR)) {

schedule();

}

www.huins.com 26

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

ret = ac97_probe_codec(&pxa_ac97_codec);if (ret != 1) {

free_irq(IRQ_AC97, NULL);GCR = GCR_ACLINK_OFF;CKEN &= ~CKEN2_AC97; return ret;

}

pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1);pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050);pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030);

}

pxa_ac97_refcount++;up(&pxa_ac97_mutex);*codec = &pxa_ac97_codec;return 0;

}

www.huins.com 27

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

void pxa_ac97_put(void)

{

down(&pxa_ac97_mutex);

pxa_ac97_refcount--;

if (!pxa_ac97_refcount) {

GCR = GCR_ACLINK_OFF;

CKEN &= ~CKEN2_AC97;

free_irq(IRQ_AC97, NULL);

}

up(&pxa_ac97_mutex);

}

EXPORT_SYMBOL(pxa_ac97_get);

EXPORT_SYMBOL(pxa_ac97_put);

www.huins.com 28

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

static int ac97_audio_open(struct inode *inode, struct file *file)

{

return pxa_audio_attach(inode, file, &ac97_audio_state);

}

static struct file_operations ac97_audio_fops = {

open: ac97_audio_open,

owner: THIS_MODULE

};

www.huins.com 29

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

static int __init pxa_ac97_init(void){

int ret;struct ac97_codec *dummy;

ret = pxa_ac97_get(&dummy);if (ret)

return ret;

ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1);

pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1);

return 0;}

Minor number 를 자동으로 잡아준다 .

www.huins.com 30

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-ac97.c source 분석 (Cont’)

static void __exit pxa_ac97_exit(void)

{

unregister_sound_dsp(ac97_audio_state.dev_dsp);

unregister_sound_mixer(pxa_ac97_codec.dev_mixer);

pxa_ac97_put();

}

module_init(pxa_ac97_init);

module_exit(pxa_ac97_exit);

Insmod 실행 시 호출 :모듈을 커널에 등록

rmmod 시 호출

www.huins.com 31

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석

void pxa_audio_clear_buf(audio_stream_t * s)

{

DECLARE_WAITQUEUE(wait, current);

int frag;

if (!s->buffers)

return;

/* Ensure DMA isn't running */

set_current_state(TASK_UNINTERRUPTIBLE);

add_wait_queue(&s->stop_wq, &wait);

DCSR(s->dma_ch) = DCSR_STOPIRQEN;

schedule();

remove_wait_queue(&s->stop_wq, &wait);

Set to true whe thread is in WaitForSingleObject

Audio buffer array

dma chnnel number

Stop interrupt enbale(read/write)

www.huins.com 32

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

/* free DMA buffers */for (frag = 0; frag < s->nbfrags; frag++) {

audio_buf_t *b = &s->buffers[frag];if (!b->master)

continue;consistent_free(b->data, b->master, b->dma_desc->dsadr);

}

/* free descriptor ring */if (s->buffers->dma_desc)

consistent_free(s->buffers->dma_desc, s->nbfrags * s->descs_per_frag * DMA_DESC

_SIZE,s->dma_desc_phys);

/* free buffer structure array */kfree(s->buffers);s->buffers = NULL;

}

Buffer 를 clear 한다는 메시지와 함께 buffer 를 free 한다 .

www.huins.com 33

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

static int audio_set_fragments(audio_stream_t *s, int val)

{

if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN)

return -EBUSY;

if (s->buffers)

audio_clear_buf(s);

s->nbfrags = (val >> 16) & 0x7FFF;

val &= 0xffff;

if (val < 5)

val = 5;

if (val > 15)

val = 15;

Device or resource is busy

Number of fragments

19

www.huins.com 34

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

s->fragsize = 1 << val;

if (s->nbfrags < 2)

s->nbfrags = 2;

if (s->nbfrags * s->fragsize > 256 * 1024)

s->nbfrags = 256 * 1024 / s->fragsize;

if (audio_setup_buf(s))

return -ENOMEM;

return val|(s->nbfrags << 16);

}

www.huins.com 35

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

static int audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)

{const char *buffer0 = buffer;audio_state_t *state = (audio_state_t *)file->private_data;audio_stream_t *s = state->output_stream;int chunksize, ret = 0;

if (ppos != &file->f_pos)return -ESPIPE;

if (s->mapped)return -ENXIO;

if (!s->buffers && audio_setup_buf(s))return -ENOMEM;

Illegal seek

No such device or address

Out of memory

www.huins.com 36

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

while (count > 0) {audio_buf_t *b = &s->buffers[s->usr_frag];

/* Grab a fragment */if (file->f_flags & O_NONBLOCK) {

ret = -EAGAIN;if (down_trylock(&s->sem))

break;} else {

ret = -ERESTARTSYS;if (down_interruptible(&s->sem))

break;}

/* Feed the current buffer */chunksize = s->fragsize - b->offset;if (chunksize > count)

chunksize = count;

00004

Try again : 35

www.huins.com 37

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

if (copy_from_user(b->data + b->offset, buffer, chunksize)) {up(&s->sem);return -EFAULT;

}

b->offset += chunksize;buffer += chunksize;count -= chunksize;if (b->offset < s->fragsize) {

up(&s->sem);break;

}/*activate DMA on current buffer*/b->offset = 0;b->dma_desc->ddadr &= ~DDADR_STOP;if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {

DDADR(s->dma_ch) = b->dma_desc->ddadr;DCSR(s->dma_ch) = DCSR_RUN;

}

Bad address

Unlock this fragment’s checkpoint descriptor and kick DMA if it is idle.

Using checkpoint descriptors allows for control operations without the need for

stopping the DMA channel if it is already running.

www.huins.com 38

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

/* move the index to the next fragment */

if (++s->usr_frag >= s->nbfrags)

s->usr_frag = 0;

}

if ((buffer - buffer0))

ret = buffer - buffer0;

return ret;

}

www.huins.com 39

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

static int audio_read(struct file *file, char *buffer, size_t count,

loff_t * ppos)

{

char *buffer0 = buffer;

audio_state_t *state = file->private_data;

audio_stream_t *s = state->input_stream;

int chunksize, ret = 0;

if (ppos != &file->f_pos)

return -ESPIPE;

if (s->mapped)

return -ENXIO;

if (!s->buffers && audio_setup_buf(s))

return -ENOMEM;

www.huins.com 40

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

while (count > 0) {audio_buf_t *b = &s->buffers[s->usr_frag];

/* prime DMA */if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {

DDADR(s->dma_ch) = s->buffers[s->dma_frag].dma_desc->ddadr;

DCSR(s->dma_ch) = DCSR_RUN;}

/* Wait for a buffer to become full */if (file->f_flags & O_NONBLOCK) {

ret = -EAGAIN;if (down_trylock(&s->sem))

break;} else {

ret = -ERESTARTSYS;if (down_interruptible(&s->sem))

break;}

www.huins.com 41

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

/* Grab data from current buffer */chunksize = s->fragsize - b->offset;if (chunksize > count)

chunksize = count;if (copy_to_user(buffer, b->data + b->offset, chunksize)) {

up(&s->sem);return -EFAULT;

}b->offset += chunksize;buffer += chunksize;count -= chunksize;if (b->offset < s->fragsize) {

up(&s->sem);break;

}

www.huins.com 42

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

b->offset = 0;

b->dma_desc->ddadr &= ~DDADR_STOP;

/* move the index to the next fragment */

if (++s->usr_frag >= s->nbfrags)

s->usr_frag = 0;

}

if ((buffer - buffer0))

ret = buffer - buffer0;

return ret;

}

www.huins.com 43

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

static int audio_release(struct inode *inode, struct file *file)

{

audio_state_t *state = file->private_data;

down(&state->sem);

if (file->f_mode & FMODE_READ) {

audio_clear_buf(state->input_stream);

*state->input_stream->drcmr = 0;

pxa_free_dma(state->input_stream->dma_ch);

state->rd_ref = 0;

}

1

DMA request channel to use

DMA channel number

www.huins.com 44

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

if (file->f_mode & FMODE_WRITE) {

audio_sync(file);

audio_clear_buf(state->output_stream);

*state->output_stream->drcmr = 0;

pxa_free_dma(state->output_stream->dma_ch);

state->wr_ref = 0;

}

up(&state->sem);

return 0;

}

2

www.huins.com 45

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

int pxa_audio_attach(struct inode *inode, struct file *file, audio_state_t *stat

e){

audio_stream_t *is = state->input_stream;audio_stream_t *os = state->output_stream;int err;

down(&state->sem);

/* access control */err = -ENODEV;if ((file->f_mode & FMODE_WRITE) && !os)

goto out;if ((file->f_mode & FMODE_READ) && !is)

goto out;

No such device

www.huins.com 46

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

err = -EBUSY;if ((file->f_mode & FMODE_WRITE) && state->wr_ref)

goto out;if ((file->f_mode & FMODE_READ) && state->rd_ref)

goto out;

/* request DMA channels */if (file->f_mode & FMODE_WRITE) {

err = pxa_request_dma(os->name, DMA_PRIO_LOW, audio_dma_irq, os);

if (err < 0)goto out;

os->dma_ch = err;}

8

www.huins.com 47

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

if (file->f_mode & FMODE_READ) {err = pxa_request_dma(is->name, DMA_PRIO_LOW,

audio_dma_irq, is);if (err < 0) {

if (file->f_mode & FMODE_WRITE) {*os->drcmr = 0;pxa_free_dma(os->dma_ch);

}goto out;

}is->dma_ch = err;

}file->private_data = state;file->f_op->release = audio_release;file->f_op->write = audio_write;file->f_op->read = audio_read;file->f_op->mmap = audio_mmap;file->f_op->poll = audio_poll;file->f_op->ioctl = audio_ioctl;file->f_op->llseek = no_llseek;

www.huins.com 48

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

if ((file->f_mode & FMODE_WRITE)) {state->wr_ref = 1;os->fragsize = AUDIO_FRAGSIZE_DEFAULT;os->nbfrags = AUDIO_NBFRAGS_DEFAULT;os->output = 1;os->mapped = 0;init_waitqueue_head(&os->frag_wq);init_waitqueue_head(&os->stop_wq);*os->drcmr = os->dma_ch | DRCMR_MAPVLD;

}if (file->f_mode & FMODE_READ) {

state->rd_ref = 1;is->fragsize = AUDIO_FRAGSIZE_DEFAULT;is->nbfrags = AUDIO_NBFRAGS_DEFAULT;is->output = 0;is->mapped = 0;init_waitqueue_head(&is->frag_wq);init_waitqueue_head(&is->stop_wq);*is->drcmr = is->dma_ch | DRCMR_MAPVLD;

}

8192

8

www.huins.com 49

14.2 Sound Device Driver14.2 Sound Device Driver 의 원리의 원리 pxa-audio.c source 분석 (cont’d)

err = 0;

out:

up(&state->sem);

return err;

}

EXPORT_SYMBOL(pxa_audio_attach);

EXPORT_SYMBOL(pxa_audio_clear_buf);

www.huins.com 50

14.3 Audio 14.3 Audio 구동구동 mixer

/dev 디렉토리에 가면 mixer 가 있음을 확인할 수 있다 .

www.huins.com 51

14.3 Audio 14.3 Audio 구동구동 mixer

$ mixer vol 100 이라고 입력하면 volume 을 설정할 수 있다 .

www.huins.com 52

14.3 Audio 14.3 Audio 구동구동 mixer

pcm 볼륨를 설정할 수 있다 .

www.huins.com 53

14.3 Audio 14.3 Audio 구동구동 mixer

/usr/bin 디렉토리 밑에 madplay 가 있음을 확인할 수 있다 .

www.huins.com 54

14.3 Audio 14.3 Audio 구동구동 mixer

위와 같이 입력하면 PXA255 보드에 있는 sample.mp3 파일을 실행 할 수 있다 . 실행시키면 ‘연애 소설 OST’ 를 들을 수 있다 .

www.huins.com 55

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

/* www.opensound.com */

#define DEFAULT_DSP_SPEED 8000

#define RECORD 0

#define PLAY 1

#define AUDIO "/dev/dsp"

int prof = APF_NORMAL;

int timelimit=0, dsp_speed = DEFAULT_DSP_SPEED, dsp_stereo=0;

int samplesize = 8;

int quiet_mode = 0;

int audio, abuf_size;

int direction, omode;

int blksize=0;

int fragsize=0;

char *audiobuf;

int c;

char audio_name[20] = AUDIO;

www.huins.com 56

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

void recplay (char *name);extern void describe_error(void);

Int main (int argc, char *argv[]){

char *command; int tmp;

command = argv[0]; if (strstr (argv[0], "srec")) { direction = RECORD; omode = O_RDONLY; } else if (strstr (argv[0], "splay")) { direction = PLAY; omode = O_WRONLY; }

www.huins.com 57

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

else

{

fprintf (stderr,

"Error: command should be named either srec or splay\n");

exit (1);

}

while ((c = getopt (argc, argv, "pqs:St:b:d:B:f:")) != -1)

switch (c){

case 'S': dsp_stereo = 1;

break;

case 'q': quiet_mode = 1;

break;

case 's': dsp_speed = atoi (optarg);

if (dsp_speed < 300)

dsp_speed *= 1000;

break;

Command 가 없을 경우 error 메세지 출력

www.huins.com 58

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

case 't': timelimit = atoi (optarg); break;

case 'b': samplesize = atoi (optarg); break;

case 'B': blksize = atoi (optarg); break;

case 'd': strncpy(audio_name, optarg, 20); break;

case 'f': fragsize = 0xffff0000 | atoi (optarg); break;

case 'p': prof = APF_CPUINTENS; break;

default: fprintf (stderr, "Usage: %s [-qS] [-t secs] [-s Hz] [-b 8|12|16] [-d device] [filename]\n", command);

exit (-1); }

www.huins.com 59

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

audio = open (audio_name, omode, 0); if (audio == -1) { perror (audio_name); describe_error(); exit (-1); }

if (fragsize != 0) if (ioctl(audio, SNDCTL_DSP_SETFRAGMENT, &fragsize)== -1) {

perror("SETFRAGMENT");exit(-1);

}

tmp = samplesize; ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize); if (tmp != samplesize) { fprintf(stderr, "Unable to set the sample size\n"); exit(-1); }

Open device fail

www.huins.com 60

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

ioctl(audio, SNDCTL_DSP_PROFILE, &prof);

if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo)==-1) { fprintf (stderr, "%s: Unable to set mono/stereo\n", command); perror (audio_name); exit (-1); }

if (ioctl (audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1) { fprintf (stderr, "%s: Unable to set audio speed\n", command); perror (audio_name); exit (-1); } if (!quiet_mode) { fprintf (stderr, "Speed %d Hz ", dsp_speed); if (dsp_stereo)

fprintf (stderr, "(stereo)\n"); else

fprintf (stderr, "(mono)\n"); if (samplesize != 8) fprintf(stderr, "%d bits per sample\n", samplesize); }

www.huins.com 61

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

if (blksize > 0) abuf_size = blksize; else {

ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size); if (abuf_size < 1) { perror ("GETBLKSIZE"); exit (-1); }

} if ((audiobuf = malloc (abuf_size)) == NULL) { fprintf (stderr, "Unable to allocate input/output buffer\n"); exit (-1); } if (optind > argc - 1) recplay (NULL); else while (optind <= argc - 1) {

recplay (argv[optind++]); } close (audio); return 0;} //main() 끝

www.huins.com 62

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를를 이용한 이용한 Sound ProgrammingSound Programming

void recplay (char *name){ int fd, l;

int count, c;

if (!timelimit) count = 0x7fffffff; else { count = timelimit * dsp_speed; if (dsp_stereo)

count *= 2; if (samplesize != 8) count *= 2; }

Number of byte the program wants to read from the device.

Using an integer power of 2

www.huins.com 63

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

if (direction == PLAY) { if (!name){

fd = 0; name = "stdin"; }

else { if ((fd = open (name, O_RDONLY, 0)) == -1) { perror (name); exit (-1); } }

while (count) { c = count;

if (c > abuf_size) c = abuf_size;

c 값은 abuf_size 보다 반드시 같거나 작아야

한다 .

www.huins.com 64

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

if ((l = read (fd, audiobuf, c)) > 0) { if (write (audio, audiobuf, l) != l) {

perror (audio_name); exit (-1);}

count -= l; } else { if (l == -1) {

perror (name); exit (-1);}

count = 0; /* Stop */ }

} /* while (count) */ if (fd != 0) close (fd);}

www.huins.com 65

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

else { if (!name) {

fd = 1; name = "stdout";}

else { if ((fd = open (name, O_WRONLY | O_CREAT, 0666)) == -1) { perror (name); exit (-1); }}

while (count) { c = count; if (c > abuf_size) c = abuf_size; if ((l = read (audio, audiobuf, c)) > 0) { if (write (fd, audiobuf, l) != l) {

perror (name); exit (-1);}

count -= l; }

www.huins.com 66

14.4 OSS(Open Sound System) Interface14.4 OSS(Open Sound System) Interface 를 를 이용한 이용한 Sound ProgrammingSound Programming

if (l == -1)

{

perror (audio_name);

exit (-1);

}

} /* While count */

if (fd != 1)

close (fd);

}

}