static int play(struct audio_play *play) { struct buffer *buffer; unsigned int len; if (set_pause(0) == -1) return -1; buffer = &output[bindex]; /* wait for block to finish playing */ if (buffer->pcm_length == 0 && wait(buffer) == -1) return -1; /* prepare block */ len = audio_pcm(&buffer->pcm_data[buffer->pcm_length], play->nsamples, play->samples[0], play->samples[1], play->mode, play->stats); buffer->pcm_length += len; if (buffer->pcm_length + MAX_NSAMPLES * samplesize * 2 > samplerate * samplesize * 2) { write_dev(wave_handle, buffer); bindex = (bindex + 1) % NBUFFERS; output[bindex].pcm_length = 0; } return 0; }
error handle::write(uint32_t addr, const void *buf, size_t& sz, bool atomic) { std::unique_lock<std::recursive_mutex> lock(m_mutex); /* get a pointer so that it's not destroyed during the runtime of the function, * the pointer will be released at the end of the function */ std::shared_ptr<context> ctx = m_dev->get_context(); if(!ctx) return error::NO_CONTEXT; /* ensure valid status */ error err = status(); if(err != error::SUCCESS) return err; /* split transfer as needed */ size_t cnt = 0; const uint8_t *bufp = (uint8_t *)buf; while(sz > 0) { size_t xfer = std::min(sz, get_buffer_size()); err = write_dev(addr, buf, xfer, atomic); if(err != error::SUCCESS) return err; sz -= xfer; bufp += xfer; addr += xfer; cnt += xfer; } sz = cnt; return error::SUCCESS; }
static int drain(void) { int i, result = 0; if (set_pause(0) == -1) result = -1; if (output[bindex].pcm_length && write_dev(wave_handle, &output[bindex]) == -1) result = -1; for (i = 0; i < NBUFFERS; ++i) { if (wait(&output[i]) == -1) result = -1; } output[bindex].pcm_length = 0; return result; }
/* * Pass the block device location, offset, and data size as the command line arguments. */ int main(const int argc, const char* argv[] ) { if (argc < 5) { fprintf(stderr, "Must pass device path, offset, data size, and o'r' or 'w' as arguments\n"); return -1; } // get block device to use const char* dev = argv[1]; printf("Device is: %s\n", dev); const int offset = atoi(argv[2]); if (offset < 0) { printf("Offset must be > 0\n"); return -1; } printf("Offset is: %d\n", offset); const int size = atoi(argv[3]); if (size < 1) { printf("Size must be greater than 0\n"); return -1; } printf("Data size is: %d\n", size); const char action = argv[4][0]; if (access(dev, R_OK | W_OK) == -1) { // device does not exist perror("Device not found or cannot read/write"); return -1; } // open block device const int f = open(dev, O_RDWR | O_NONBLOCK); if (f < 0) { fprintf(stderr, "Error opening block device %s\n", dev); return -1; } if (action == WRITE) { // write const int c_wrote = write_dev(f, size, offset); if (c_wrote != size) { fprintf(stderr, "Write size did not match requested size\n"); } } else { // read const int c_read = read_dev(f, size, offset); if (c_read != size) { fprintf(stderr, "Read size did not match requested size\n"); } } // The close causes extra reads that will be captured by UART debug // Let the user complete capture before this happens printf("Complete the debug capture, then press any key to close the device file.\nWarning: This will cause extra reads!\n"); getchar(); printf("Closing device\n"); if(close(f) < 0) { perror("Failed to close device file"); } return 0; }
error handle::write_dev(uint32_t addr, const void *buf, size_t& sz, bool atomic) { auto p = m_hwdev.lock(); return p ? p->write_dev(addr, buf, sz, atomic) : error::DISCONNECTED; }