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