1 /*
2  *
3  *
4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  */
16 
17 #include "pvrusb2-ioread.h"
18 #include "pvrusb2-debug.h"
19 #include <linux/errno.h>
20 #include <linux/string.h>
21 #include <linux/mm.h>
22 #include <linux/slab.h>
23 #include <linux/mutex.h>
24 #include <linux/uaccess.h>
25 
26 #define BUFFER_COUNT 32
27 #define BUFFER_SIZE PAGE_ALIGN(0x4000)
28 
29 struct pvr2_ioread {
30 	struct pvr2_stream *stream;
31 	char *buffer_storage[BUFFER_COUNT];
32 	char *sync_key_ptr;
33 	unsigned int sync_key_len;
34 	unsigned int sync_buf_offs;
35 	unsigned int sync_state;
36 	unsigned int sync_trashed_count;
37 	int enabled;         // Streaming is on
38 	int spigot_open;     // OK to pass data to client
39 	int stream_running;  // Passing data to client now
40 
41 	/* State relevant to current buffer being read */
42 	struct pvr2_buffer *c_buf;
43 	char *c_data_ptr;
44 	unsigned int c_data_len;
45 	unsigned int c_data_offs;
46 	struct mutex mutex;
47 };
48 
49 static int pvr2_ioread_init(struct pvr2_ioread *cp)
50 {
51 	unsigned int idx;
52 
53 	cp->stream = NULL;
54 	mutex_init(&cp->mutex);
55 
56 	for (idx = 0; idx < BUFFER_COUNT; idx++) {
57 		cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL);
58 		if (!(cp->buffer_storage[idx])) break;
59 	}
60 
61 	if (idx < BUFFER_COUNT) {
62 		// An allocation appears to have failed
63 		for (idx = 0; idx < BUFFER_COUNT; idx++) {
64 			if (!(cp->buffer_storage[idx])) continue;
65 			kfree(cp->buffer_storage[idx]);
66 		}
67 		return -ENOMEM;
68 	}
69 	return 0;
70 }
71 
72 static void pvr2_ioread_done(struct pvr2_ioread *cp)
73 {
74 	unsigned int idx;
75 
76 	pvr2_ioread_setup(cp,NULL);
77 	for (idx = 0; idx < BUFFER_COUNT; idx++) {
78 		if (!(cp->buffer_storage[idx])) continue;
79 		kfree(cp->buffer_storage[idx]);
80 	}
81 }
82 
83 struct pvr2_ioread *pvr2_ioread_create(void)
84 {
85 	struct pvr2_ioread *cp;
86 	cp = kzalloc(sizeof(*cp),GFP_KERNEL);
87 	if (!cp) return NULL;
88 	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
89 	if (pvr2_ioread_init(cp) < 0) {
90 		kfree(cp);
91 		return NULL;
92 	}
93 	return cp;
94 }
95 
96 void pvr2_ioread_destroy(struct pvr2_ioread *cp)
97 {
98 	if (!cp) return;
99 	pvr2_ioread_done(cp);
100 	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
101 	if (cp->sync_key_ptr) {
102 		kfree(cp->sync_key_ptr);
103 		cp->sync_key_ptr = NULL;
104 	}
105 	kfree(cp);
106 }
107 
108 void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
109 			      const char *sync_key_ptr,
110 			      unsigned int sync_key_len)
111 {
112 	if (!cp) return;
113 
114 	if (!sync_key_ptr) sync_key_len = 0;
115 	if ((sync_key_len == cp->sync_key_len) &&
116 	    ((!sync_key_len) ||
117 	     (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return;
118 
119 	if (sync_key_len != cp->sync_key_len) {
120 		if (cp->sync_key_ptr) {
121 			kfree(cp->sync_key_ptr);
122 			cp->sync_key_ptr = NULL;
123 		}
124 		cp->sync_key_len = 0;
125 		if (sync_key_len) {
126 			cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL);
127 			if (cp->sync_key_ptr) {
128 				cp->sync_key_len = sync_key_len;
129 			}
130 		}
131 	}
132 	if (!cp->sync_key_len) return;
133 	memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len);
134 }
135 
136 static void pvr2_ioread_stop(struct pvr2_ioread *cp)
137 {
138 	if (!(cp->enabled)) return;
139 	pvr2_trace(PVR2_TRACE_START_STOP,
140 		   "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
141 	pvr2_stream_kill(cp->stream);
142 	cp->c_buf = NULL;
143 	cp->c_data_ptr = NULL;
144 	cp->c_data_len = 0;
145 	cp->c_data_offs = 0;
146 	cp->enabled = 0;
147 	cp->stream_running = 0;
148 	cp->spigot_open = 0;
149 	if (cp->sync_state) {
150 		pvr2_trace(PVR2_TRACE_DATA_FLOW,
151 			   "/*---TRACE_READ---*/ sync_state <== 0");
152 		cp->sync_state = 0;
153 	}
154 }
155 
156 static int pvr2_ioread_start(struct pvr2_ioread *cp)
157 {
158 	int stat;
159 	struct pvr2_buffer *bp;
160 	if (cp->enabled) return 0;
161 	if (!(cp->stream)) return 0;
162 	pvr2_trace(PVR2_TRACE_START_STOP,
163 		   "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
164 	while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != NULL) {
165 		stat = pvr2_buffer_queue(bp);
166 		if (stat < 0) {
167 			pvr2_trace(PVR2_TRACE_DATA_FLOW,
168 				   "/*---TRACE_READ---*/ pvr2_ioread_start id=%p error=%d",
169 				   cp,stat);
170 			pvr2_ioread_stop(cp);
171 			return stat;
172 		}
173 	}
174 	cp->enabled = !0;
175 	cp->c_buf = NULL;
176 	cp->c_data_ptr = NULL;
177 	cp->c_data_len = 0;
178 	cp->c_data_offs = 0;
179 	cp->stream_running = 0;
180 	if (cp->sync_key_len) {
181 		pvr2_trace(PVR2_TRACE_DATA_FLOW,
182 			   "/*---TRACE_READ---*/ sync_state <== 1");
183 		cp->sync_state = 1;
184 		cp->sync_trashed_count = 0;
185 		cp->sync_buf_offs = 0;
186 	}
187 	cp->spigot_open = 0;
188 	return 0;
189 }
190 
191 struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp)
192 {
193 	return cp->stream;
194 }
195 
196 int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
197 {
198 	int ret;
199 	unsigned int idx;
200 	struct pvr2_buffer *bp;
201 
202 	mutex_lock(&cp->mutex);
203 	do {
204 		if (cp->stream) {
205 			pvr2_trace(PVR2_TRACE_START_STOP,
206 				   "/*---TRACE_READ---*/ pvr2_ioread_setup (tear-down) id=%p",
207 				   cp);
208 			pvr2_ioread_stop(cp);
209 			pvr2_stream_kill(cp->stream);
210 			if (pvr2_stream_get_buffer_count(cp->stream)) {
211 				pvr2_stream_set_buffer_count(cp->stream,0);
212 			}
213 			cp->stream = NULL;
214 		}
215 		if (sp) {
216 			pvr2_trace(PVR2_TRACE_START_STOP,
217 				   "/*---TRACE_READ---*/ pvr2_ioread_setup (setup) id=%p",
218 				   cp);
219 			pvr2_stream_kill(sp);
220 			ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
221 			if (ret < 0) {
222 				mutex_unlock(&cp->mutex);
223 				return ret;
224 			}
225 			for (idx = 0; idx < BUFFER_COUNT; idx++) {
226 				bp = pvr2_stream_get_buffer(sp,idx);
227 				pvr2_buffer_set_buffer(bp,
228 						       cp->buffer_storage[idx],
229 						       BUFFER_SIZE);
230 			}
231 			cp->stream = sp;
232 		}
233 	} while (0);
234 	mutex_unlock(&cp->mutex);
235 
236 	return 0;
237 }
238 
239 int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
240 {
241 	int ret = 0;
242 	if ((!fl) == (!(cp->enabled))) return ret;
243 
244 	mutex_lock(&cp->mutex);
245 	do {
246 		if (fl) {
247 			ret = pvr2_ioread_start(cp);
248 		} else {
249 			pvr2_ioread_stop(cp);
250 		}
251 	} while (0);
252 	mutex_unlock(&cp->mutex);
253 	return ret;
254 }
255 
256 static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
257 {
258 	int stat;
259 
260 	while (cp->c_data_len <= cp->c_data_offs) {
261 		if (cp->c_buf) {
262 			// Flush out current buffer first.
263 			stat = pvr2_buffer_queue(cp->c_buf);
264 			if (stat < 0) {
265 				// Streaming error...
266 				pvr2_trace(PVR2_TRACE_DATA_FLOW,
267 					   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p queue_error=%d",
268 					   cp,stat);
269 				pvr2_ioread_stop(cp);
270 				return 0;
271 			}
272 			cp->c_buf = NULL;
273 			cp->c_data_ptr = NULL;
274 			cp->c_data_len = 0;
275 			cp->c_data_offs = 0;
276 		}
277 		// Now get a freshly filled buffer.
278 		cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream);
279 		if (!cp->c_buf) break; // Nothing ready; done.
280 		cp->c_data_len = pvr2_buffer_get_count(cp->c_buf);
281 		if (!cp->c_data_len) {
282 			// Nothing transferred.  Was there an error?
283 			stat = pvr2_buffer_get_status(cp->c_buf);
284 			if (stat < 0) {
285 				// Streaming error...
286 				pvr2_trace(PVR2_TRACE_DATA_FLOW,
287 					   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p buffer_error=%d",
288 					   cp,stat);
289 				pvr2_ioread_stop(cp);
290 				// Give up.
291 				return 0;
292 			}
293 			// Start over...
294 			continue;
295 		}
296 		cp->c_data_offs = 0;
297 		cp->c_data_ptr = cp->buffer_storage[
298 			pvr2_buffer_get_id(cp->c_buf)];
299 	}
300 	return !0;
301 }
302 
303 static void pvr2_ioread_filter(struct pvr2_ioread *cp)
304 {
305 	unsigned int idx;
306 	if (!cp->enabled) return;
307 	if (cp->sync_state != 1) return;
308 
309 	// Search the stream for our synchronization key.  This is made
310 	// complicated by the fact that in order to be honest with
311 	// ourselves here we must search across buffer boundaries...
312 	mutex_lock(&cp->mutex);
313 	while (1) {
314 		// Ensure we have a buffer
315 		if (!pvr2_ioread_get_buffer(cp)) break;
316 		if (!cp->c_data_len) break;
317 
318 		// Now walk the buffer contents until we match the key or
319 		// run out of buffer data.
320 		for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) {
321 			if (cp->sync_buf_offs >= cp->sync_key_len) break;
322 			if (cp->c_data_ptr[idx] ==
323 			    cp->sync_key_ptr[cp->sync_buf_offs]) {
324 				// Found the next key byte
325 				(cp->sync_buf_offs)++;
326 			} else {
327 				// Whoops, mismatched.  Start key over...
328 				cp->sync_buf_offs = 0;
329 			}
330 		}
331 
332 		// Consume what we've walked through
333 		cp->c_data_offs += idx;
334 		cp->sync_trashed_count += idx;
335 
336 		// If we've found the key, then update state and get out.
337 		if (cp->sync_buf_offs >= cp->sync_key_len) {
338 			cp->sync_trashed_count -= cp->sync_key_len;
339 			pvr2_trace(PVR2_TRACE_DATA_FLOW,
340 				   "/*---TRACE_READ---*/ sync_state <== 2 (skipped %u bytes)",
341 				   cp->sync_trashed_count);
342 			cp->sync_state = 2;
343 			cp->sync_buf_offs = 0;
344 			break;
345 		}
346 
347 		if (cp->c_data_offs < cp->c_data_len) {
348 			// Sanity check - should NEVER get here
349 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
350 				   "ERROR: pvr2_ioread filter sync problem len=%u offs=%u",
351 				   cp->c_data_len,cp->c_data_offs);
352 			// Get out so we don't get stuck in an infinite
353 			// loop.
354 			break;
355 		}
356 
357 		continue; // (for clarity)
358 	}
359 	mutex_unlock(&cp->mutex);
360 }
361 
362 int pvr2_ioread_avail(struct pvr2_ioread *cp)
363 {
364 	int ret;
365 	if (!(cp->enabled)) {
366 		// Stream is not enabled; so this is an I/O error
367 		return -EIO;
368 	}
369 
370 	if (cp->sync_state == 1) {
371 		pvr2_ioread_filter(cp);
372 		if (cp->sync_state == 1) return -EAGAIN;
373 	}
374 
375 	ret = 0;
376 	if (cp->stream_running) {
377 		if (!pvr2_stream_get_ready_count(cp->stream)) {
378 			// No data available at all right now.
379 			ret = -EAGAIN;
380 		}
381 	} else {
382 		if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) {
383 			// Haven't buffered up enough yet; try again later
384 			ret = -EAGAIN;
385 		}
386 	}
387 
388 	if ((!(cp->spigot_open)) != (!(ret == 0))) {
389 		cp->spigot_open = (ret == 0);
390 		pvr2_trace(PVR2_TRACE_DATA_FLOW,
391 			   "/*---TRACE_READ---*/ data is %s",
392 			   cp->spigot_open ? "available" : "pending");
393 	}
394 
395 	return ret;
396 }
397 
398 int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
399 {
400 	unsigned int copied_cnt;
401 	unsigned int bcnt;
402 	const char *src;
403 	int stat;
404 	int ret = 0;
405 	unsigned int req_cnt = cnt;
406 
407 	if (!cnt) {
408 		pvr2_trace(PVR2_TRACE_TRAP,
409 			   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p ZERO Request? Returning zero.",
410 cp);
411 		return 0;
412 	}
413 
414 	stat = pvr2_ioread_avail(cp);
415 	if (stat < 0) return stat;
416 
417 	cp->stream_running = !0;
418 
419 	mutex_lock(&cp->mutex);
420 	do {
421 
422 		// Suck data out of the buffers and copy to the user
423 		copied_cnt = 0;
424 		if (!buf) cnt = 0;
425 		while (1) {
426 			if (!pvr2_ioread_get_buffer(cp)) {
427 				ret = -EIO;
428 				break;
429 			}
430 
431 			if (!cnt) break;
432 
433 			if (cp->sync_state == 2) {
434 				// We're repeating the sync key data into
435 				// the stream.
436 				src = cp->sync_key_ptr + cp->sync_buf_offs;
437 				bcnt = cp->sync_key_len - cp->sync_buf_offs;
438 			} else {
439 				// Normal buffer copy
440 				src = cp->c_data_ptr + cp->c_data_offs;
441 				bcnt = cp->c_data_len - cp->c_data_offs;
442 			}
443 
444 			if (!bcnt) break;
445 
446 			// Don't run past user's buffer
447 			if (bcnt > cnt) bcnt = cnt;
448 
449 			if (copy_to_user(buf,src,bcnt)) {
450 				// User supplied a bad pointer?
451 				// Give up - this *will* cause data
452 				// to be lost.
453 				ret = -EFAULT;
454 				break;
455 			}
456 			cnt -= bcnt;
457 			buf += bcnt;
458 			copied_cnt += bcnt;
459 
460 			if (cp->sync_state == 2) {
461 				// Update offset inside sync key that we're
462 				// repeating back out.
463 				cp->sync_buf_offs += bcnt;
464 				if (cp->sync_buf_offs >= cp->sync_key_len) {
465 					// Consumed entire key; switch mode
466 					// to normal.
467 					pvr2_trace(PVR2_TRACE_DATA_FLOW,
468 						   "/*---TRACE_READ---*/ sync_state <== 0");
469 					cp->sync_state = 0;
470 				}
471 			} else {
472 				// Update buffer offset.
473 				cp->c_data_offs += bcnt;
474 			}
475 		}
476 
477 	} while (0);
478 	mutex_unlock(&cp->mutex);
479 
480 	if (!ret) {
481 		if (copied_cnt) {
482 			// If anything was copied, return that count
483 			ret = copied_cnt;
484 		} else {
485 			// Nothing copied; suggest to caller that another
486 			// attempt should be tried again later
487 			ret = -EAGAIN;
488 		}
489 	}
490 
491 	pvr2_trace(PVR2_TRACE_DATA_FLOW,
492 		   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p request=%d result=%d",
493 		   cp,req_cnt,ret);
494 	return ret;
495 }
496