static int mcp2221_raw_event()

in hid-mcp2221.c [710:822]


static int mcp2221_raw_event(struct hid_device *hdev,
				struct hid_report *report, u8 *data, int size)
{
	u8 *buf;
	struct mcp2221 *mcp = hid_get_drvdata(hdev);

	switch (data[0]) {

	case MCP2221_I2C_WR_DATA:
	case MCP2221_I2C_WR_NO_STOP:
	case MCP2221_I2C_RD_DATA:
	case MCP2221_I2C_RD_RPT_START:
		switch (data[1]) {
		case MCP2221_SUCCESS:
			mcp->status = 0;
			break;
		default:
			mcp->status = mcp_get_i2c_eng_state(mcp, data, 2);
		}
		complete(&mcp->wait_in_report);
		break;

	case MCP2221_I2C_PARAM_OR_STATUS:
		switch (data[1]) {
		case MCP2221_SUCCESS:
			if ((mcp->txbuf[3] == MCP2221_I2C_SET_SPEED) &&
				(data[3] != MCP2221_I2C_SET_SPEED)) {
				mcp->status = -EAGAIN;
				break;
			}
			if (data[20] & MCP2221_I2C_MASK_ADDR_NACK) {
				mcp->status = -ENXIO;
				break;
			}
			mcp->status = mcp_get_i2c_eng_state(mcp, data, 8);
			break;
		default:
			mcp->status = -EIO;
		}
		complete(&mcp->wait_in_report);
		break;

	case MCP2221_I2C_GET_DATA:
		switch (data[1]) {
		case MCP2221_SUCCESS:
			if (data[2] == MCP2221_I2C_ADDR_NACK) {
				mcp->status = -ENXIO;
				break;
			}
			if (!mcp_get_i2c_eng_state(mcp, data, 2)
				&& (data[3] == 0)) {
				mcp->status = 0;
				break;
			}
			if (data[3] == 127) {
				mcp->status = -EIO;
				break;
			}
			if (data[2] == MCP2221_I2C_READ_COMPL) {
				buf = mcp->rxbuf;
				memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
				mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
				mcp->status = 0;
				break;
			}
			mcp->status = -EIO;
			break;
		default:
			mcp->status = -EIO;
		}
		complete(&mcp->wait_in_report);
		break;

	case MCP2221_GPIO_GET:
		switch (data[1]) {
		case MCP2221_SUCCESS:
			if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) ||
				(data[mcp->gp_idx + 1] == MCP2221_ALT_F_NOT_GPIOD)) {
				mcp->status = -ENOENT;
			} else {
				mcp->status = !!data[mcp->gp_idx];
				mcp->gpio_dir = data[mcp->gp_idx + 1];
			}
			break;
		default:
			mcp->status = -EAGAIN;
		}
		complete(&mcp->wait_in_report);
		break;

	case MCP2221_GPIO_SET:
		switch (data[1]) {
		case MCP2221_SUCCESS:
			if ((data[mcp->gp_idx] == MCP2221_ALT_F_NOT_GPIOV) ||
				(data[mcp->gp_idx - 1] == MCP2221_ALT_F_NOT_GPIOV)) {
				mcp->status = -ENOENT;
			} else {
				mcp->status = 0;
			}
			break;
		default:
			mcp->status = -EAGAIN;
		}
		complete(&mcp->wait_in_report);
		break;

	default:
		mcp->status = -EIO;
		complete(&mcp->wait_in_report);
	}

	return 1;
}