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