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; }
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; }
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; }
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; }
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; }
/* * * 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); }
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 } }
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); } } }
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; } }
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; } }
static void minivosc_timer_stop(struct minivosc_device *mydev) { dbg2("minivosc_timer_stop"); del_timer(&mydev->timer); }
/* * * 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; }