int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt) { unsigned int copied_cnt; unsigned int bcnt; const char *src; int stat; int ret = 0; unsigned int req_cnt = cnt; if (!cnt) { pvr2_trace(PVR2_TRACE_TRAP, "/*---TRACE_READ---*/ pvr2_ioread_read id=%p ZERO Request? Returning zero.", cp); return 0; } stat = pvr2_ioread_avail(cp); if (stat < 0) return stat; cp->stream_running = !0; mutex_lock(&cp->mutex); do { // Suck data out of the buffers and copy to the user copied_cnt = 0; if (!buf) cnt = 0; while (1) { if (!pvr2_ioread_get_buffer(cp)) { ret = -EIO; break; } if (!cnt) break; if (cp->sync_state == 2) { // We're repeating the sync key data into // the stream. src = cp->sync_key_ptr + cp->sync_buf_offs; bcnt = cp->sync_key_len - cp->sync_buf_offs; } else { // Normal buffer copy src = cp->c_data_ptr + cp->c_data_offs; bcnt = cp->c_data_len - cp->c_data_offs; } if (!bcnt) break; // Don't run past user's buffer if (bcnt > cnt) bcnt = cnt; if (copy_to_user(buf,src,bcnt)) { // User supplied a bad pointer? // Give up - this *will* cause data // to be lost. ret = -EFAULT; break; } cnt -= bcnt; buf += bcnt; copied_cnt += bcnt; if (cp->sync_state == 2) { // Update offset inside sync key that we're // repeating back out. cp->sync_buf_offs += bcnt; if (cp->sync_buf_offs >= cp->sync_key_len) { // Consumed entire key; switch mode // to normal. pvr2_trace(PVR2_TRACE_DATA_FLOW, "/*---TRACE_READ---*/ sync_state <== 0"); cp->sync_state = 0; } } else { // Update buffer offset. cp->c_data_offs += bcnt; } } } while (0); mutex_unlock(&cp->mutex); if (!ret) { if (copied_cnt) { // If anything was copied, return that count ret = copied_cnt; } else { // Nothing copied; suggest to caller that another // attempt should be tried again later ret = -EAGAIN; } } pvr2_trace(PVR2_TRACE_DATA_FLOW, "/*---TRACE_READ---*/ pvr2_ioread_read id=%p request=%d result=%d", cp,req_cnt,ret); return ret; }
int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt) { unsigned int copied_cnt; unsigned int bcnt; const char *src; int stat; int ret = 0; unsigned int req_cnt = cnt; if (!cnt) { pvr2_trace(PVR2_TRACE_TRAP, "/*---TRACE_READ---*/ pvr2_ioread_read id=%p" " ZERO Request? Returning zero.",cp); return 0; } stat = pvr2_ioread_avail(cp); if (stat < 0) return stat; cp->stream_running = !0; mutex_lock(&cp->mutex); do { copied_cnt = 0; if (!buf) cnt = 0; while (1) { if (!pvr2_ioread_get_buffer(cp)) { ret = -EIO; break; } if (!cnt) break; if (cp->sync_state == 2) { src = cp->sync_key_ptr + cp->sync_buf_offs; bcnt = cp->sync_key_len - cp->sync_buf_offs; } else { src = cp->c_data_ptr + cp->c_data_offs; bcnt = cp->c_data_len - cp->c_data_offs; } if (!bcnt) break; if (bcnt > cnt) bcnt = cnt; if (copy_to_user(buf,src,bcnt)) { ret = -EFAULT; break; } cnt -= bcnt; buf += bcnt; copied_cnt += bcnt; if (cp->sync_state == 2) { cp->sync_buf_offs += bcnt; if (cp->sync_buf_offs >= cp->sync_key_len) { pvr2_trace(PVR2_TRACE_DATA_FLOW, "/*---TRACE_READ---*/" " sync_state <== 0"); cp->sync_state = 0; } } else { cp->c_data_offs += bcnt; } } } while (0); mutex_unlock(&cp->mutex); if (!ret) { if (copied_cnt) { ret = copied_cnt; } else { ret = -EAGAIN; } } pvr2_trace(PVR2_TRACE_DATA_FLOW, "/*---TRACE_READ---*/ pvr2_ioread_read" " id=%p request=%d result=%d", cp,req_cnt,ret); return ret; }