drivers/usb/serial/metro-usb.c
Source file repositories/reference/linux-study-clean/drivers/usb/serial/metro-usb.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/serial/metro-usb.c- Extension
.c- Size
- 10121 bytes
- Lines
- 372
- Domain
- Driver Families
- Bucket
- drivers/usb
- 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.
- 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/tty.hlinux/module.hlinux/usb.hlinux/errno.hlinux/slab.hlinux/tty_driver.hlinux/tty_flip.hlinux/moduleparam.hlinux/spinlock.hlinux/uaccess.hlinux/usb/serial.h
Detected Declarations
struct metrousb_privatefunction metrousb_is_unidirectional_modefunction metrousb_calc_num_portsfunction metrousb_send_unidirectional_cmdfunction metrousb_read_int_callbackfunction metrousb_cleanupfunction metrousb_openfunction metrousb_set_modem_ctrlfunction metrousb_port_probefunction metrousb_port_removefunction metrousb_throttlefunction metrousb_tiocmgetfunction metrousb_tiocmsetfunction metrousb_unthrottle
Annotated Snippet
struct metrousb_private {
spinlock_t lock;
int throttled;
unsigned long control_state;
};
/* Device table list. */
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) },
{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
{ USB_DEVICE_INTERFACE_CLASS(0x0c2e, 0x0730, 0xff) }, /* MS7820 */
{ }, /* Terminating entry. */
};
MODULE_DEVICE_TABLE(usb, id_table);
/* UNI-Directional mode commands for device configure */
#define UNI_CMD_OPEN 0x80
#define UNI_CMD_CLOSE 0xFF
static int metrousb_is_unidirectional_mode(struct usb_serial *serial)
{
u16 product_id = le16_to_cpu(serial->dev->descriptor.idProduct);
return product_id == FOCUS_PRODUCT_ID_UNI;
}
static int metrousb_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{
if (metrousb_is_unidirectional_mode(serial)) {
if (epds->num_interrupt_out == 0) {
dev_err(&serial->interface->dev, "interrupt-out endpoint missing\n");
return -ENODEV;
}
}
return 1;
}
static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port)
{
int ret;
int actual_len;
u8 *buffer_cmd = NULL;
if (!metrousb_is_unidirectional_mode(port->serial))
return 0;
buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL);
if (!buffer_cmd)
return -ENOMEM;
*buffer_cmd = cmd;
ret = usb_interrupt_msg(port->serial->dev,
usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
buffer_cmd, sizeof(cmd),
&actual_len, USB_CTRL_SET_TIMEOUT);
kfree(buffer_cmd);
if (ret < 0)
return ret;
else if (actual_len != sizeof(cmd))
return -EIO;
return 0;
}
static void metrousb_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
int throttled = 0;
int result = 0;
dev_dbg(&port->dev, "%s\n", __func__);
switch (urb->status) {
case 0:
/* Success status, read from the port. */
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* urb has been terminated. */
dev_dbg(&port->dev,
"%s - urb shutting down, error code=%d\n",
__func__, urb->status);
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/tty.h`, `linux/module.h`, `linux/usb.h`, `linux/errno.h`, `linux/slab.h`, `linux/tty_driver.h`, `linux/tty_flip.h`.
- Detected declarations: `struct metrousb_private`, `function metrousb_is_unidirectional_mode`, `function metrousb_calc_num_ports`, `function metrousb_send_unidirectional_cmd`, `function metrousb_read_int_callback`, `function metrousb_cleanup`, `function metrousb_open`, `function metrousb_set_modem_ctrl`, `function metrousb_port_probe`, `function metrousb_port_remove`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: source 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.