Exemple #1
0
static irqreturn_t lpc_pci_interrupt( int irq, void *ptr, struct pt_regs *regs )
    {
    DEV *dev = (DEV *)ptr;
    u32 cport;
    
    u16 IntCsr = inw(dev->PlxIntCsrPort);
//    dev->PciIntCount++;
//    info("? %s(): dev=%08X IntCsr=%04X", __FUNCTION__, (uint)dev, IntCsr);
    if (IntCsr == 0xFFFF)  return IRQ_NONE;		// Can't read PLX
    if (inb(dev->cport) & 8)  return IRQ_NONE;		// Its not for me
    
    dbg2("+ %s(): dev=%08X", __FUNCTION__, (uint)dev);
    
    del_timer( &dev->drvtimer );

    cport = dev->cport;
    dev->ctl &= 0xEF;				// Clear interrupt flipflop (PCI)
    SETCTL;
    SETCTL;
    SETCTL;
    dev->ctl |= 0x10;               // CLR_IFF_CMND
    SETCTL;

    sm_stub(dev);
    dbg2("- %s(): dev=%08X return", __FUNCTION__, (uint)dev);
    return IRQ_HANDLED;
    }
Exemple #2
0
static int minivosc_pcm_prepare(struct snd_pcm_substream *ss)
{
	// copied from aloop-kernel.c

	// for one, we could get mydev from ss->private_data...
	// here we try it via ss->runtime->private_data instead.
	// turns out, this type of call via runtime->private_data
	// ends up with mydev as null pointer causing SIGSEGV
	// .. UNLESS runtime->private_data is assigned in _open?
	struct snd_pcm_runtime *runtime = ss->runtime;
	struct minivosc_device *mydev = runtime->private_data;
	unsigned int bps;

	dbg("%s", __func__);

	bps = runtime->rate * runtime->channels; // params requested by user app (arecord, audacity)
	bps *= snd_pcm_format_width(runtime->format);
	bps /= 8;
	if (bps <= 0)
		return -EINVAL;

	mydev->buf_pos = 0;
	mydev->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
	dbg2("	bps: %u; runtime->buffer_size: %lu; mydev->pcm_buffer_size: %u", bps, runtime->buffer_size, mydev->pcm_buffer_size);
	if (ss->stream == SNDRV_PCM_STREAM_CAPTURE) {
		/* clear capture buffer */
		mydev->silent_size = mydev->pcm_buffer_size;
		//memset(runtime->dma_area, 0, mydev->pcm_buffer_size);
		// we're in char land here, so let's mark prepare buffer with value 45 (signature)
		// this turns out to set everything permanently throughout - not just first buffer,
		// even though it runs only at start?
		memset(runtime->dma_area, 45, mydev->pcm_buffer_size);
	}

	if (!mydev->running) {
		mydev->irq_pos = 0;
		mydev->period_update_pending = 0;
	}


	mutex_lock(&mydev->cable_lock);
	if (!(mydev->valid & ~(1 << ss->stream))) {
		mydev->pcm_bps = bps;
		mydev->pcm_period_size =
			frames_to_bytes(runtime, runtime->period_size);
		mydev->period_size_frac = frac_pos(mydev->pcm_period_size);

	}
	mydev->valid |= 1 << ss->stream;
	mutex_unlock(&mydev->cable_lock);

	dbg2("	pcm_period_size: %u; period_size_frac: %u", mydev->pcm_period_size, mydev->period_size_frac);

	return 0;
}
Exemple #3
0
static snd_pcm_uframes_t minivosc_pcm_pointer(struct snd_pcm_substream *ss)
{
	//copied from aloop-kernel.c
	struct snd_pcm_runtime *runtime = ss->runtime;
	struct minivosc_device *mydev= runtime->private_data;

	dbg2("+minivosc_pointer ");
	minivosc_pos_update(mydev);
	dbg2("+	bytes_to_frames(: %lu, mydev->buf_pos: %d", bytes_to_frames(runtime, mydev->buf_pos),mydev->buf_pos);
	return bytes_to_frames(runtime, mydev->buf_pos);

}
void* playback_thread(void* thread_param) {
    audio_blob_t* audio_blob = (audio_blob_t*)thread_param;
    void* audio_ptr;
    int play_samples;
    int samples_left = (audio_blob->len_bytes - audio_blob->used_bytes) / audio_blob->frame_size;
    int buffer_samples = audio_blob->buffer_size / audio_blob->frame_size;
    int result;
    int stop_flag = 0;

    dbg1("playback thread started with audio blob at %p\n", thread_param);

    while (samples_left > 0 && !stop_flag) {
        grab_mutex(audio_blob->play_list_item->mutex);
        stop_flag = audio_blob->play_list_item->stop_flag;
        release_mutex(audio_blob->play_list_item->mutex);

        dbg2("loop iteration with stop flag: %d\n", stop_flag);

        if (samples_left < audio_blob->buffer_size) {
            play_samples = samples_left;
        } else {
            play_samples = buffer_samples;
        }
        audio_ptr = audio_blob->buffer_obj.buf + (size_t)(audio_blob->used_bytes);
        result = snd_pcm_writei(audio_blob->handle, audio_ptr, play_samples);
        if (result < 0) {
            dbg2("snd_pcm_writei error code: %d\n", result);

            result = snd_pcm_recover(audio_blob->handle, result, 0);
            if (result < 0) {
                dbg2("unrecoverable error - code: %d\n", result);

                /* unrecoverable error */
                break;
            }
        } else {
            audio_blob->used_bytes += result * audio_blob->frame_size;
        }

        samples_left = (audio_blob->len_bytes - audio_blob->used_bytes) / audio_blob->frame_size;
    }

    dbg2("done buffering audio - cleaning up\n");

    snd_pcm_drain(audio_blob->handle);
    snd_pcm_close(audio_blob->handle);
    destroy_audio_blob(audio_blob);

    dbg1("playback thread done");

    pthread_exit(0);
}
INT8U Can232::exec() {
    dbg2("Command received:", inputString);
    lw232LastErr = parseAndRunCommand();
    switch (lw232LastErr) {
    case LW232_OK:
        Serial.write(LW232_RET_ASCII_OK);
        break;
    case LW232_OK_SMALL:
        Serial.write(LW232_RET_ASCII_OK_SMALL);
        Serial.write(LW232_RET_ASCII_OK);
        break;
    case LW232_OK_BIG:
        Serial.write(LW232_RET_ASCII_OK_BIG);
        Serial.write(LW232_RET_ASCII_OK);
        break;
    case LW232_ERR_NOT_IMPLEMENTED:
        // Choose behavior: will it fail or not when not implemented command comes in. Some can monitors might be affected by this selection.
        Serial.write(LW232_RET_ASCII_ERROR);
        //Serial.write(LW232_RET_ASCII_OK); 
        break;
    default:
        Serial.write(LW232_RET_ASCII_ERROR);
    }
    return 0;
}
Exemple #6
0
int main(int argc,char **argv)
{
//  debug_builder dbg;
//  null_builder dbg;
//  csv_writer<file_out> dbg((file_out(stdout))); // CPP11: dbg{{stdout}}
//  csv_writer<file_out> dbg(file_out(stdout),'\'',',',true);

#if 1
    SimpleCSV::Table tbl;
    SimpleCSV::builder dbg(tbl);
#endif

    csvparser cp(dbg,'\'');
    cp(
        "\n"
        "1, 's' , 3,4   a\n"
        ",1,2,3,4\n"
        " asdf, 'asd''df', s\n"
    );

    csv_writer<file_out> dbg2(file_out(stdout),'\'',',',true);
    tbl.write(dbg2);

    return 0;
}
Exemple #7
0
static irqreturn_t lpc_isa_interrupt( int irq, void *ptr, struct pt_regs *regs )
    {
    DEV *dev;
    
    dev = (DEV *)ptr;
    if( inb(dev->cport) & 8 ) return IRQ_NONE;		// Its not for me
    
    dbg2("+ %s(): dev=%08X", __FUNCTION__, (uint)dev);
    
    del_timer( &dev->drvtimer );
    outb(0, dev->rport);			// Clear interrupt flipflop (ISA)
    sm_stub( dev );
    
    dbg2("- %s(): dev=%08X return", __FUNCTION__, (uint)dev);
	return IRQ_HANDLED;
    }
Exemple #8
0
/*
 *
 * Timer functions
 *
 */
static void minivosc_timer_start(struct minivosc_device *mydev)
{
	unsigned long tick;
	dbg2("minivosc_timer_start: mydev->period_size_frac: %u; mydev->irq_pos: %u jiffies: %lu pcm_bps %u", mydev->period_size_frac, mydev->irq_pos, jiffies, mydev->pcm_bps);
	tick = mydev->period_size_frac - mydev->irq_pos;
	tick = (tick + mydev->pcm_bps - 1) / mydev->pcm_bps;
	mydev->timer.expires = jiffies + tick;
	add_timer(&mydev->timer);
}
Exemple #9
0
static void minivosc_xfer_buf(struct minivosc_device *mydev, unsigned int count)
{

	dbg2(">minivosc_xfer_buf: count: %d ", count );

	switch (mydev->running) {
	case CABLE_CAPTURE:
		minivosc_fill_capture_buf(mydev, count);
		break;
	}

		if (mydev->running) {
// activate this buf_pos calculation, either if V3 is defined,
//  or if no COPYALG is defined (which also handles lone BUFFERMARKS)
#if defined(COPYALG_V3) || !(defined(COPYALG_V1) || defined(COPYALG_V2) || defined(COPYALG_V3))
			// here the (auto)increase of buf_pos is handled
			mydev->buf_pos += count;
			mydev->buf_pos %= mydev->pcm_buffer_size;
			dbg2(">	: mydev->buf_pos: %d ", mydev->buf_pos); // */
#endif
		}
}
Exemple #10
0
static void minivosc_timer_function(unsigned long data)
{
	struct minivosc_device *mydev = (struct minivosc_device *)data;

	if (!mydev->running)
		return;

	dbg2("minivosc_timer_function: running ");
	minivosc_pos_update(mydev);
	// SET OFF THE TIMER HERE:
	minivosc_timer_start(mydev);

	if (mydev->period_update_pending)
	{
		mydev->period_update_pending = 0;

		if (mydev->running)
		{
			dbg2("	: calling snd_pcm_period_elapsed");
			snd_pcm_period_elapsed(mydev->substream);
		}
	}
}
Exemple #11
0
static void minivosc_pos_update(struct minivosc_device *mydev)
{
	unsigned int last_pos, count;
	unsigned long delta;

	if (!mydev->running)
		return;

	dbg2("*minivosc_pos_update: running ");

	delta = jiffies - mydev->last_jiffies;
	dbg2("*	: jiffies %lu, ->last_jiffies %lu, delta %lu", jiffies, mydev->last_jiffies, delta);

	if (!delta)
		return;

	mydev->last_jiffies += delta;

	last_pos = byte_pos(mydev->irq_pos);
	mydev->irq_pos += delta * mydev->pcm_bps;
	count = byte_pos(mydev->irq_pos) - last_pos;
	dbg2("*	: last_pos %d, c->irq_pos %d, count %d", last_pos, mydev->irq_pos, count);

	if (!count)
		return;

	// FILL BUFFER HERE
	minivosc_xfer_buf(mydev, count);

	if (mydev->irq_pos >= mydev->period_size_frac)
	{
		dbg2("*	: mydev->irq_pos >= mydev->period_size_frac %d", mydev->period_size_frac);
		mydev->irq_pos %= mydev->period_size_frac;
		mydev->period_update_pending = 1;
	}
}
Exemple #12
0
static void minivosc_fill_capture_buf(struct minivosc_device *mydev, unsigned int bytes)
{
	char *dst = mydev->substream->runtime->dma_area;
	unsigned int dst_off = mydev->buf_pos; // buf_pos is in bytes, not in samples !
	float wrdat; // was char - value to fill silent_size with
	unsigned int dpos = 0; //added
#if defined(COPYALG_V1) || defined(COPYALG_V2)
	int i = 0; //added
	int mylift = 0; //added
#endif
#if defined(COPYALG_V1)
	unsigned int remain = 0; //added
	unsigned int remain2 = 0; //added
	unsigned int wvftocopy = 0; //added
#endif
#if defined(COPYALG_V2)
	int j = 0; //added
#endif
#if defined(COPYALG_V3)
#endif


	dbg2("_ minivosc_fill_capture_buf ss %d bs %d bytes %d buf_pos %d sizeof %d jiffies %lu", mydev->silent_size, mydev->pcm_buffer_size, bytes, dst_off, sizeof(*dst), jiffies);

#if defined(COPYALG_V1)
	// loop v1.. fill waveform until end of 'bytes'..
	// using memcpy for copying/filling
	//*
	while (dpos < bytes-1)
	{
		mylift = mydev->wvf_lift*10 - 10;
		// create modified - 'lifted' - values of waveform:
		for (i=0; i<wvfsz;) {
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		      wvfdat[i] = wvfdat2[i%21]+mylift; i++;
		}

		remain = bytes - dpos;
		remain2 = mydev->pcm_buffer_size - mydev->buf_pos;
		if (remain < wvfsz) wvftocopy = remain; //not wvfsz - remain!
		if (remain2 < wvfsz) wvftocopy = remain2; //also see if "big" PCM buffer wraps!
		else wvftocopy = wvfsz;
		if (mydev->wvf_pos > 0) wvftocopy -= mydev->wvf_pos;

		dbg2("::: buf_pos %d; dpos %d; wvf_pos %d; wvftocopy %d; remain %d; remain2 %d; wvfsz %d; wvf_lift %d", mydev->buf_pos, dpos, mydev->wvf_pos, wvftocopy, remain, remain2, wvfsz, mydev->wvf_lift);

		memcpy(dst + mydev->buf_pos, &wvfdat[mydev->wvf_pos], wvftocopy);

		dpos += wvftocopy;
		mydev->buf_pos += wvftocopy; //added if there isn't (auto)increase of buf_pos in xfer_buf
		mydev->wvf_pos += wvftocopy;
		if (mydev->wvf_pos >= wvfsz) { // we should wrap waveform here..
			mydev->wvf_pos -= wvfsz;
			// also handle lift here..
			mydev->wvf_lift++;
			if (mydev->wvf_lift >=4) mydev->wvf_lift = 0;
		}
		//added if there isn't (auto)increase of buf_pos in xfer_buf
		// there may be some misalignments here still, though...
		if (mydev->buf_pos >= mydev->pcm_buffer_size) {
			mydev->buf_pos = 0;
			break; //we don;t really need this.. but maybe here...?
		}
		if (dpos >= bytes-1) break;
	} // end loop v1 */
#endif //defined(COPYALG_V1)

#if defined(COPYALG_V2)
	// hmm... for this loop, v2,  I was getting prepare signature (45), if
	//   mydev->buf_pos autoincrements (wraps) in minivosc_xfer_buf ;
	// however, for more correct, we calculate 'buf_pos' here instead..
	// using direct assignment of elements for copying/filling
	//*
	for (j=0; j<bytes; j++) {
		mylift = mydev->wvf_lift*10 - 10;
		for (i=0; i<sizeof(wvfdat); i++) {
			wvfdat[i] = wvfdat2[i]+mylift;
		}

		dst[mydev->buf_pos] = wvfdat[mydev->wvf_pos];
		dpos++; mydev->buf_pos++;
		mydev->wvf_pos++;

		if (mydev->wvf_pos >= wvfsz) { // we should wrap waveform here..
			mydev->wvf_pos = 0;
			// also handle lift here..
			mydev->wvf_lift++;
			if (mydev->wvf_lift >=4) mydev->wvf_lift = 0;
		}
		if (mydev->buf_pos >= mydev->pcm_buffer_size) {
			mydev->buf_pos = 0;
			//break; //we don;t really need this
		}
		if (dpos >= bytes) break;
	} // end loop v2 */
#endif //defined(COPYALG_V2)

#if defined(COPYALG_V3)
	// as in copy_play_buf in aloop-kernel.c, where we had:
	//~ char *src = play->substream->runtime->dma_area;
	//~ char *dst = capt->substream->runtime->dma_area;
	// 'buf_pos' here is calculated in _xfer_buf, and
	//   the waveform wrapping is not correct
	// using memcpy for copying/filling

	for (;;) {
		unsigned int size = bytes;
		if (mydev->wvf_pos + size > wvfsz)
			size = wvfsz - mydev->wvf_pos;
		if (dst_off + size > mydev->pcm_buffer_size)
			size = mydev->pcm_buffer_size - dst_off;

		memcpy(dst + dst_off, wvfdat + mydev->wvf_pos, size);

		if (size < mydev->silent_size)
			mydev->silent_size -= size;
		else
			mydev->silent_size = 0;
		bytes -= size;
		if (!bytes)
			break;
		mydev->wvf_pos = (mydev->wvf_pos + size) % wvfsz;
		dst_off = (dst_off + size) % mydev->pcm_buffer_size;
	}
#endif //defined(COPYALG_V3)

#if defined(BUFFERMARKS)
	//* //set buffer marks
	//-------------
	//these two shouldn't change in repeated calls of this func:
	memset(dst+1, 160, 1); // mark start of pcm buffer
	memset(dst + mydev->pcm_buffer_size - 2, 140, 1); // mark end of pcm buffer

	memset(dst + dst_off, 120, 1); // mark start of this fill_capture_buf.
	if (dst_off==0) memset(dst + dst_off, 250, 1); // different mark if offset is zero
	// note - if marking end at dst + dst_off + bytes, it gets overwritten by next run
	memset(dst + dst_off + bytes - 2, 90, 1); // mark end fill_capture_buf.
	// end set buffer marks */
#endif //defined(BUFFERMARKS)

	if (mydev->silent_size >= mydev->pcm_buffer_size)
		return;

	// NOTE: usually, the code returns by now -
	// - it doesn't even execute past this point!
	// from here on, apparently silent_size should be handled..

	if (mydev->silent_size + bytes > mydev->pcm_buffer_size)
		bytes = mydev->pcm_buffer_size - mydev->silent_size;

	wrdat = -0.2; // value to copy, instead of 0 for silence (if needed)

	for (;;) {
		unsigned int size = bytes;
		dpos = 0; //added
		dbg2("_ clearrr..	%d", bytes);
		if (dst_off + size > mydev->pcm_buffer_size)
			size = mydev->pcm_buffer_size - dst_off;

		//memset(dst + dst_off, 255, size); //0, size);
		while (dpos < size)
		{
			memcpy(dst + dst_off + dpos, &wrdat, sizeof(wrdat));
			dpos += sizeof(wrdat);
			if (dpos >= size) break;
		}
		mydev->silent_size += size;
		bytes -= size;
		if (!bytes)
			break;
		dst_off = 0;
	}
}
Exemple #13
0
static void minivosc_timer_stop(struct minivosc_device *mydev)
{
	dbg2("minivosc_timer_stop");
	del_timer(&mydev->timer);
}
Exemple #14
0
/*
 *
 * Probe/remove functions
 *
 */
static int __devinit minivosc_probe(struct platform_device *devptr)
{

	struct snd_card *card;
	struct minivosc_device *mydev;
	int ret;

	int nr_subdevs; // how many capture substreams we want
	struct snd_pcm *pcm;

	int dev = devptr->id; // from aloop-kernel.c

	dbg("%s: probe", __func__);


	// no need to kzalloc minivosc_device separately, if the sizeof is included here
	ret = snd_card_create(index[dev], id[dev],
	                      THIS_MODULE, sizeof(struct minivosc_device), &card);

	if (ret < 0)
		goto __nodev;

	mydev = card->private_data;
	mydev->card = card;
	// MUST have mutex_init here - else crash on mutex_lock!!
	mutex_init(&mydev->cable_lock);

	dbg2("-- mydev %p", mydev);

	sprintf(card->driver, "my_driver-%s", SND_MINIVOSC_DRIVER);
	sprintf(card->shortname, "MySoundCard Audio %s", SND_MINIVOSC_DRIVER);
	sprintf(card->longname, "%s", card->shortname);


	snd_card_set_dev(card, &devptr->dev); // present in dummy, not in aloop though


	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, mydev, &dev_ops);

	if (ret < 0)
		goto __nodev;


	nr_subdevs = 1; // how many capture substreams we want
	// * we want 0 playback, and 1 capture substreams (4th and 5th arg) ..
	ret = snd_pcm_new(card, card->driver, 0, 0, nr_subdevs, &pcm);

	if (ret < 0)
		goto __nodev;


	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &minivosc_pcm_ops); // in both aloop-kernel.c and dummy.c, after snd_pcm_new...
	pcm->private_data = mydev; //here it should be dev/card struct (the one containing struct snd_card *card) - this DOES NOT end up in substream->private_data

	pcm->info_flags = 0;
	strcpy(pcm->name, card->shortname);

	/*
	trid to add this - but it crashes here:
	//mydev->substream->private_data = mydev;
	Well, first time real substream comes in, is in _open - so
	that has to be handled there.. That is: at this point, mydev->substream is null,
	and we first have a chance to set it ... in _open!
	*/

	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
	        SNDRV_DMA_TYPE_CONTINUOUS,
	        snd_dma_continuous_data(GFP_KERNEL),
	        MAX_BUFFER, MAX_BUFFER); // in both aloop-kernel.c and dummy.c, after snd_pcm_set_ops...

	if (ret < 0)
		goto __nodev;

	// * will use the snd_card_register form from aloop-kernel.c/dummy.c here..
	ret = snd_card_register(card);

	if (ret == 0)   // or... (!ret)
	{
		platform_set_drvdata(devptr, card);
		return 0; // success
	}

__nodev: // as in aloop/dummy...
	dbg("__nodev reached!!");
	snd_card_free(card); // this will autocall .dev_free (= minivosc_pcm_dev_free)
	return ret;
}