drivers/input/mouse/cypress_ps2.c

Source file repositories/reference/linux-study-clean/drivers/input/mouse/cypress_ps2.c

File Facts

System
Linux kernel
Corpus path
drivers/input/mouse/cypress_ps2.c
Extension
.c
Size
18161 bytes
Lines
676
Domain
Driver Families
Bucket
drivers/input
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rc == -EAGAIN) {
			rc = cypress_ps2_sendbyte(psmouse, 0x00);
			if (rc == -EAGAIN)
				rc = cypress_ps2_sendbyte(psmouse, 0x0a);
		}

		if (!rc) {
			rc = cypress_ps2_sendbyte(psmouse, nibble);
			if (rc == -EAGAIN)
				rc = cypress_ps2_sendbyte(psmouse, nibble);

			if (!rc)
				break;
		}
	} while (--tries > 0);

	ps2_end_command(ps2dev);

	return rc;
}

static bool cypress_verify_cmd_state(struct psmouse *psmouse, u8 cmd, u8* param)
{
	bool rate_match = false;
	bool resolution_match = false;
	int i;

	/* callers will do further checking. */
	if (cmd == CYTP_CMD_READ_CYPRESS_ID ||
	    cmd == CYTP_CMD_STANDARD_MODE ||
	    cmd == CYTP_CMD_READ_TP_METRICS)
		return true;

	if ((~param[0] & DFLT_RESP_BITS_VALID) == DFLT_RESP_BITS_VALID &&
	    (param[0] & DFLT_RESP_BIT_MODE) == DFLT_RESP_STREAM_MODE) {
		for (i = 0; i < sizeof(cytp_resolution); i++)
			if (cytp_resolution[i] == param[1])
				resolution_match = true;

		for (i = 0; i < sizeof(cytp_rate); i++)
			if (cytp_rate[i] == param[2])
				rate_match = true;

		if (resolution_match && rate_match)
			return true;
	}

	psmouse_dbg(psmouse, "verify cmd state failed.\n");
	return false;
}

static int cypress_send_ext_cmd(struct psmouse *psmouse, u8 cmd, u8 *param)
{
	u8 cmd_prefix = PSMOUSE_CMD_SETRES & 0xff;
	unsigned int resp_size = cmd == CYTP_CMD_READ_TP_METRICS ? 8 : 3;
	unsigned int ps2_cmd = (PSMOUSE_CMD_GETINFO & 0xff) | (resp_size << 8);
	int tries = CYTP_PS2_CMD_TRIES;
	int error;

	psmouse_dbg(psmouse, "send extension cmd 0x%02x, [%d %d %d %d]\n",
		 cmd, DECODE_CMD_AA(cmd), DECODE_CMD_BB(cmd),
		 DECODE_CMD_CC(cmd), DECODE_CMD_DD(cmd));

	do {
		cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_DD(cmd));
		cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_CC(cmd));
		cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_BB(cmd));
		cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_AA(cmd));

		error = ps2_command(&psmouse->ps2dev, param, ps2_cmd);
		if (error) {
			psmouse_dbg(psmouse, "Command 0x%02x failed: %d\n",
				    cmd, error);
		} else {
			psmouse_dbg(psmouse,
				    "Command 0x%02x response data (0x): %*ph\n",
				    cmd, resp_size, param);

			if (cypress_verify_cmd_state(psmouse, cmd, param))
				return 0;
		}
	} while (--tries > 0);

	return -EIO;
}

int cypress_detect(struct psmouse *psmouse, bool set_properties)
{
	u8 param[3];

Annotation

Implementation Notes