drivers/net/can/can327.c

Source file repositories/reference/linux-study-clean/drivers/net/can/can327.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/can327.c
Extension
.c
Size
30909 bytes
Lines
1143
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops can327_netdev_ops = {
	.ndo_open = can327_netdev_open,
	.ndo_stop = can327_netdev_close,
	.ndo_start_xmit = can327_netdev_start_xmit,
};

static const struct ethtool_ops can327_ethtool_ops = {
	.get_ts_info = ethtool_op_get_ts_info,
};

static bool can327_is_valid_rx_char(u8 c)
{
	static const bool lut_char_is_valid['z'] = {
		['\r'] = true,
		[' '] = true,
		['.'] = true,
		['0'] = true, true, true, true, true,
		['5'] = true, true, true, true, true,
		['<'] = true,
		[CAN327_READY_CHAR] = true,
		['?'] = true,
		['A'] = true, true, true, true, true, true, true,
		['H'] = true, true, true, true, true, true, true,
		['O'] = true, true, true, true, true, true, true,
		['V'] = true, true, true, true, true,
		['a'] = true,
		['b'] = true,
		['v'] = true,
		[CAN327_DUMMY_CHAR] = true,
	};
	BUILD_BUG_ON(CAN327_DUMMY_CHAR >= 'z');

	return (c < ARRAY_SIZE(lut_char_is_valid) && lut_char_is_valid[c]);
}

/* Handle incoming ELM327 ASCII data.
 * This will not be re-entered while running, but other ldisc
 * functions may be called in parallel.
 */
static void can327_ldisc_rx(struct tty_struct *tty, const u8 *cp,
			    const u8 *fp, size_t count)
{
	struct can327 *elm = tty->disc_data;
	size_t first_new_char_idx;

	if (elm->uart_side_failure)
		return;

	spin_lock_bh(&elm->lock);

	/* Store old rxfill, so can327_parse_rxbuf() will have
	 * the option of skipping already checked characters.
	 */
	first_new_char_idx = elm->rxfill;

	while (count--) {
		if (elm->rxfill >= CAN327_SIZE_RXBUF) {
			netdev_err(elm->dev,
				   "Receive buffer overflowed. Bad chip or wiring? count = %zu",
				   count);
			goto uart_failure;
		}
		if (fp && *fp++) {
			netdev_err(elm->dev,
				   "Error in received character stream. Check your wiring.");
			goto uart_failure;
		}

		/* Ignore NUL characters, which the PIC microcontroller may
		 * inadvertently insert due to a known hardware bug.
		 * See ELM327 documentation, which refers to a Microchip PIC
		 * bug description.
		 */
		if (*cp) {
			/* Check for stray characters on the UART line.
			 * Likely caused by bad hardware.
			 */
			if (!can327_is_valid_rx_char(*cp)) {
				netdev_err(elm->dev,
					   "Received illegal character %02x.\n",
					   *cp);
				goto uart_failure;
			}

			elm->rxbuf[elm->rxfill++] = *cp;
		}

		cp++;
	}

Annotation

Implementation Notes