drivers/media/usb/pwc/pwc-if.c
Source file repositories/reference/linux-study-clean/drivers/media/usb/pwc/pwc-if.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/media/usb/pwc/pwc-if.c- Extension
.c- Size
- 35311 bytes
- Lines
- 1230
- Domain
- Driver Families
- Bucket
- drivers/media
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/errno.hlinux/init.hlinux/mm.hlinux/module.hlinux/poll.hlinux/slab.hlinux/usb/input.hlinux/vmalloc.hasm/io.hpwc.hpwc-kiara.hpwc-timon.hpwc-dec23.hpwc-dec1.htrace/events/pwc.h
Detected Declarations
function pwc_free_urb_bufferfunction pwc_snapshot_buttonfunction pwc_frame_completefunction pwc_isoc_handlerfunction pwc_isoc_initfunction pwc_iso_stopfunction pwc_iso_freefunction pwc_isoc_cleanupfunction pwc_cleanup_queued_bufsfunction pwc_video_releasefunction queue_setupfunction buffer_initfunction buffer_preparefunction buffer_finishfunction buffer_cleanupfunction buffer_queuefunction start_streamingfunction stop_streamingfunction usb_pwc_probefunction usb_pwc_disconnect
Annotated Snippet
if (ptr[1] == 1 && ptr[0] & 0x10) {
PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
pdev->drop_frames += 2;
}
if ((ptr[0] ^ pdev->vmirror) & 0x01) {
pwc_snapshot_button(pdev, ptr[0] & 0x01);
}
if ((ptr[0] ^ pdev->vmirror) & 0x02) {
if (ptr[0] & 0x02)
PWC_TRACE("Image is mirrored.\n");
else
PWC_TRACE("Image is normal.\n");
}
pdev->vmirror = ptr[0] & 0x03;
/* Sometimes the trailer of the 730 is still sent as a 4 byte packet
after a short frame; this condition is filtered out specifically. A 4 byte
frame doesn't make sense anyway.
So we get either this sequence:
drop_bit set -> 4 byte frame -> short frame -> good frame
Or this one:
drop_bit set -> short frame -> good frame
So we drop either 3 or 2 frames in all!
*/
if (fbuf->filled == 4)
pdev->drop_frames++;
} else if (pdev->type == 740 || pdev->type == 720) {
unsigned char *ptr = (unsigned char *)fbuf->data;
if ((ptr[0] ^ pdev->vmirror) & 0x01) {
pwc_snapshot_button(pdev, ptr[0] & 0x01);
}
pdev->vmirror = ptr[0] & 0x03;
}
/* In case we were instructed to drop the frame, do so silently. */
if (pdev->drop_frames > 0) {
pdev->drop_frames--;
} else {
/* Check for underflow first */
if (fbuf->filled < pdev->frame_total_size) {
PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes); discarded.\n",
fbuf->filled);
} else {
fbuf->vb.field = V4L2_FIELD_NONE;
fbuf->vb.sequence = pdev->vframe_count;
vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
pdev->fill_buf = NULL;
pdev->vsync = 0;
}
} /* !drop_frames */
pdev->vframe_count++;
}
/* This gets called for the Isochronous pipe (video). This is done in
* interrupt time, so it has to be fast, not crash, and not stall. Neat.
*/
static void pwc_isoc_handler(struct urb *urb)
{
struct pwc_device *pdev = (struct pwc_device *)urb->context;
struct device *dmadev = urb->dev->bus->sysdev;
int i, fst, flen;
unsigned char *iso_buf = NULL;
trace_pwc_handler_enter(urb, pdev);
if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN) {
PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronously.\n",
urb, urb->status == -ENOENT ? "" : "a");
return;
}
if (pdev->fill_buf == NULL)
pdev->fill_buf = pwc_get_next_fill_buf(pdev);
if (urb->status != 0) {
const char *errmsg;
errmsg = "Unknown";
switch(urb->status) {
case -ENOSR: errmsg = "Buffer error (overrun)"; break;
case -EPIPE: errmsg = "Stalled (device not responding)"; break;
case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
case -ETIME: errmsg = "Device does not respond"; break;
}
PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
urb->status, errmsg);
/* Give up after a number of contiguous errors */
if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
Annotation
- Immediate include surface: `linux/errno.h`, `linux/init.h`, `linux/mm.h`, `linux/module.h`, `linux/poll.h`, `linux/slab.h`, `linux/usb/input.h`, `linux/vmalloc.h`.
- Detected declarations: `function pwc_free_urb_buffer`, `function pwc_snapshot_button`, `function pwc_frame_complete`, `function pwc_isoc_handler`, `function pwc_isoc_init`, `function pwc_iso_stop`, `function pwc_iso_free`, `function pwc_isoc_cleanup`, `function pwc_cleanup_queued_bufs`, `function pwc_video_release`.
- Atlas domain: Driver Families / drivers/media.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.