drivers/usb/serial/usb_wwan.c
Source file repositories/reference/linux-study-clean/drivers/usb/serial/usb_wwan.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/serial/usb_wwan.c- Extension
.c- Size
- 16313 bytes
- Lines
- 659
- Domain
- Driver Families
- Bucket
- drivers/usb
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/kernel.hlinux/jiffies.hlinux/errno.hlinux/slab.hlinux/tty.hlinux/tty_flip.hlinux/module.hlinux/bitops.hlinux/uaccess.hlinux/usb.hlinux/usb/cdc.hlinux/usb/serial.hlinux/serial.husb-wwan.h
Detected Declarations
function Copyrightfunction usb_wwan_dtr_rtsfunction usb_wwan_tiocmgetfunction usb_wwan_tiocmsetfunction usb_wwan_writefunction usb_wwan_indat_callbackfunction usb_wwan_outdat_callbackfunction usb_wwan_write_roomfunction usb_wwan_chars_in_bufferfunction usb_wwan_openfunction unbusy_queued_urbfunction usb_wwan_closefunction voidfunction usb_wwan_port_probefunction usb_wwan_port_removefunction stop_urbsfunction usb_wwan_suspendfunction usb_wwan_submit_delayed_urbsfunction usb_wwan_resumeexport usb_wwan_dtr_rtsexport usb_wwan_tiocmgetexport usb_wwan_tiocmsetexport usb_wwan_writeexport usb_wwan_write_roomexport usb_wwan_chars_in_bufferexport usb_wwan_openexport usb_wwan_closeexport usb_wwan_port_probeexport usb_wwan_port_removeexport usb_wwan_suspendexport usb_wwan_resume
Annotated Snippet
if (test_and_set_bit(i, &portdata->out_busy)) {
if (time_before(jiffies,
portdata->tx_start_time[i] + 10 * HZ))
continue;
usb_unlink_urb(this_urb);
continue;
}
dev_dbg(&port->dev, "%s: endpoint %d buf %d\n", __func__,
usb_pipeendpoint(this_urb->pipe), i);
err = usb_autopm_get_interface_async(port->serial->interface);
if (err < 0) {
clear_bit(i, &portdata->out_busy);
break;
}
/* send the data */
memcpy(this_urb->transfer_buffer, buf, todo);
this_urb->transfer_buffer_length = todo;
spin_lock_irqsave(&intfdata->susp_lock, flags);
if (intfdata->suspended) {
usb_anchor_urb(this_urb, &portdata->delayed);
spin_unlock_irqrestore(&intfdata->susp_lock, flags);
} else {
intfdata->in_flight++;
spin_unlock_irqrestore(&intfdata->susp_lock, flags);
err = usb_submit_urb(this_urb, GFP_ATOMIC);
if (err) {
dev_err(&port->dev,
"%s: submit urb %d failed: %d\n",
__func__, i, err);
clear_bit(i, &portdata->out_busy);
spin_lock_irqsave(&intfdata->susp_lock, flags);
intfdata->in_flight--;
spin_unlock_irqrestore(&intfdata->susp_lock,
flags);
usb_autopm_put_interface_async(port->serial->interface);
break;
}
}
portdata->tx_start_time[i] = jiffies;
buf += todo;
left -= todo;
}
count -= left;
dev_dbg(&port->dev, "%s: wrote (did %d)\n", __func__, count);
return count;
}
EXPORT_SYMBOL(usb_wwan_write);
static void usb_wwan_indat_callback(struct urb *urb)
{
int err;
int endpoint;
struct usb_serial_port *port;
struct device *dev;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
endpoint = usb_pipeendpoint(urb->pipe);
port = urb->context;
dev = &port->dev;
if (status) {
dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n",
__func__, status, endpoint);
/* don't resubmit on fatal errors */
if (status == -ESHUTDOWN || status == -ENOENT)
return;
} else {
if (urb->actual_length) {
tty_insert_flip_string(&port->port, data,
urb->actual_length);
tty_flip_buffer_push(&port->port);
} else
dev_dbg(dev, "%s: empty read urb received\n", __func__);
}
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
if (err != -EPERM && err != -ENODEV) {
dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
__func__, err);
/* busy also in error unless we are killed */
usb_mark_last_busy(port->serial->dev);
}
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/jiffies.h`, `linux/errno.h`, `linux/slab.h`, `linux/tty.h`, `linux/tty_flip.h`, `linux/module.h`, `linux/bitops.h`.
- Detected declarations: `function Copyright`, `function usb_wwan_dtr_rts`, `function usb_wwan_tiocmget`, `function usb_wwan_tiocmset`, `function usb_wwan_write`, `function usb_wwan_indat_callback`, `function usb_wwan_outdat_callback`, `function usb_wwan_write_room`, `function usb_wwan_chars_in_buffer`, `function usb_wwan_open`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.