static void pvr2_ioread_filter(struct pvr2_ioread *cp) { unsigned int idx; if (!cp->enabled) return; if (cp->sync_state != 1) return; // Search the stream for our synchronization key. This is made // complicated by the fact that in order to be honest with // ourselves here we must search across buffer boundaries... mutex_lock(&cp->mutex); while (1) { // Ensure we have a buffer if (!pvr2_ioread_get_buffer(cp)) break; if (!cp->c_data_len) break; // Now walk the buffer contents until we match the key or // run out of buffer data. for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) { if (cp->sync_buf_offs >= cp->sync_key_len) break; if (cp->c_data_ptr[idx] == cp->sync_key_ptr[cp->sync_buf_offs]) { // Found the next key byte (cp->sync_buf_offs)++; } else { // Whoops, mismatched. Start key over... cp->sync_buf_offs = 0; } } // Consume what we've walked through cp->c_data_offs += idx; cp->sync_trashed_count += idx; // If we've found the key, then update state and get out. if (cp->sync_buf_offs >= cp->sync_key_len) { cp->sync_trashed_count -= cp->sync_key_len; pvr2_trace(PVR2_TRACE_DATA_FLOW, "/*---TRACE_READ---*/" " sync_state <== 2 (skipped %u bytes)", cp->sync_trashed_count); cp->sync_state = 2; cp->sync_buf_offs = 0; break; } if (cp->c_data_offs < cp->c_data_len) { // Sanity check - should NEVER get here pvr2_trace(PVR2_TRACE_ERROR_LEGS, "ERROR: pvr2_ioread filter sync problem" " len=%u offs=%u", cp->c_data_len,cp->c_data_offs); // Get out so we don't get stuck in an infinite // loop. break; } continue; // (for clarity) } mutex_unlock(&cp->mutex); }
static void pvr2_ioread_filter(struct pvr2_ioread *cp) { unsigned int idx; if (!cp->enabled) return; if (cp->sync_state != 1) return; mutex_lock(&cp->mutex); while (1) { if (!pvr2_ioread_get_buffer(cp)) break; if (!cp->c_data_len) break; for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) { if (cp->sync_buf_offs >= cp->sync_key_len) break; if (cp->c_data_ptr[idx] == cp->sync_key_ptr[cp->sync_buf_offs]) { (cp->sync_buf_offs)++; } else { cp->sync_buf_offs = 0; } } cp->c_data_offs += idx; cp->sync_trashed_count += idx; if (cp->sync_buf_offs >= cp->sync_key_len) { cp->sync_trashed_count -= cp->sync_key_len; pvr2_trace(PVR2_TRACE_DATA_FLOW, "/*---TRACE_READ---*/" " sync_state <== 2 (skipped %u bytes)", cp->sync_trashed_count); cp->sync_state = 2; cp->sync_buf_offs = 0; break; } if (cp->c_data_offs < cp->c_data_len) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "ERROR: pvr2_ioread filter sync problem" " len=%u offs=%u", cp->c_data_len,cp->c_data_offs); break; } continue; } mutex_unlock(&cp->mutex); }
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; }