示例#1
0
static int rmi_i2c_write_block(struct rmi_phys_device *phys, u16 addr,
			       const void *buf, const int len)
{
	struct i2c_client *client = to_i2c_client(phys->dev);
	struct rmi_i2c_data *data = phys->data;
	int retval;
	int tx_size = len + 1;

	mutex_lock(&data->page_mutex);

	if (!data->tx_buf || data->tx_buf_size < tx_size) {
		if (data->tx_buf)
			devm_kfree(&client->dev, data->tx_buf);
		data->tx_buf_size = tx_size + BUFFER_SIZE_INCREMENT;
		data->tx_buf = devm_kzalloc(&client->dev, data->tx_buf_size,
					    GFP_KERNEL);
		if (!data->tx_buf) {
			data->tx_buf_size = 0;
			retval = -ENOMEM;
			goto exit;
		}
	}
	data->tx_buf[0] = addr & 0xff;
	memcpy(data->tx_buf + 1, buf, len);

	if (RMI_I2C_PAGE(addr) != data->page) {
		retval = rmi_set_page(phys, RMI_I2C_PAGE(addr));
		if (retval < 0)
			goto exit;
	}

	if (COMMS_DEBUG(data)) {
		retval = copy_to_debug_buf(&client->dev, data, (u8 *) buf, len);
		if (!retval)
			dev_dbg(&client->dev, "writes %d bytes at %#06x:%s\n",
				len, addr, data->debug_buf);
	}

	phys->info.tx_count++;
	phys->info.tx_bytes += tx_size;
	retval = i2c_master_send(client, data->tx_buf, tx_size);
	if (retval < 0)
		phys->info.tx_errs++;
	else
		retval--; /* don't count the address byte */

exit:
	mutex_unlock(&data->page_mutex);
	return retval;
}
示例#2
0
static int rmi_i2c_read_block(struct rmi_phys_device *phys, u16 addr,
			      void *buf, const int len)
{
	struct i2c_client *client = to_i2c_client(phys->dev);
	struct rmi_i2c_data *data = phys->data;
	u8 txbuf[1] = {addr & 0xff};
	int retval;

	mutex_lock(&data->page_mutex);

	if (RMI_I2C_PAGE(addr) != data->page) {
		retval = rmi_set_page(phys, RMI_I2C_PAGE(addr));
		if (retval < 0)
			goto exit;
	}

	if (COMMS_DEBUG(data))
		dev_dbg(&client->dev, "writes 1 bytes: %02x\n", txbuf[0]);

	phys->info.tx_count++;
	phys->info.tx_bytes += sizeof(txbuf);
	retval = i2c_master_send(client, txbuf, sizeof(txbuf));
	if (retval != sizeof(txbuf)) {
		phys->info.tx_errs++;
		retval = (retval < 0) ? retval : -EIO;
		goto exit;
	}

	retval = i2c_master_recv(client, (u8 *) buf, len);

	phys->info.rx_count++;
	phys->info.rx_bytes += len;
	if (retval < 0)
		phys->info.rx_errs++;
	else if (COMMS_DEBUG(data)) {
		retval = copy_to_debug_buf(&client->dev, data, (u8 *) buf, len);
		if (!retval)
			dev_dbg(&client->dev, "read %d bytes at %#06x:%s\n",
				len, addr, data->debug_buf);
	}

exit:
	mutex_unlock(&data->page_mutex);
	return retval;
}
示例#3
0
static int rmi_hid_write_block(struct rmi_transport_device *xport, u16 addr,
			       const void *buf, const int len)
{
        struct hid_device *hdev = to_hid_device(xport->dev);
	struct rmi_hid_data *data = xport->data;
	int ret;

	mutex_lock(&data->page_mutex);

	if (RMI_HID_PAGE(addr) != data->page) {
		ret = rmi_set_page(xport, RMI_HID_PAGE(addr));
		if (ret < 0)
			goto exit;
	}

	if (COMMS_DEBUG(data)) {
		ret = copy_to_debug_buf(&hdev->dev, data, (u8 *) buf, len);
		if (!ret)
			dev_dbg(&hdev->dev, "writes %d bytes at %#06x:%s\n",
				len, addr, data->debug_buf);
	}

	xport->info.tx_count++;
	xport->info.tx_bytes += len;

	data->writeReport[RMI_HID_REPORT_ID] = RMI_WRITE_REPORT_ID;
	data->writeReport[RMI_HID_WRITE_OUTPUT_COUNT] = len;
	data->writeReport[RMI_HID_WRITE_OUTPUT_ADDR] = addr & 0xFF;
	data->writeReport[RMI_HID_WRITE_OUTPUT_ADDR + 1] = (addr >> 8) & 0xFF;
	memcpy(&data->writeReport[RMI_HID_WRITE_OUTPUT_DATA], buf, len);

	ret = rmi_hid_write_report(hdev, data->writeReport,
					data->output_report_size);
	if (ret != data->output_report_size) {
		dev_err(&hdev->dev, "failed to send output report (%d)\n", ret);
		goto exit;
	}

exit:
	mutex_unlock(&data->page_mutex);
	return ret;
}
示例#4
0
/*SMB version 2 block write - wrapper over ic2_smb_write_block */
static int smb_v2_block_write(struct rmi_phys_device *phys,
			u8 commandcode, u8 *buf, int len)
{
	struct i2c_client *client = to_i2c_client(phys->dev);
	struct rmi_smb_data *data = phys->data;
	int tx_size = len + 1;
	int retval;

	if (!data->tx_buf || data->tx_buf_size < tx_size) {
		if (data->tx_buf)
			devm_kfree(&client->dev, data->tx_buf);
		data->tx_buf_size = tx_size + BUFFER_SIZE_INCREMENT;
		data->tx_buf = devm_kzalloc(&client->dev, data->tx_buf_size,
					    GFP_KERNEL);
		if (!data->tx_buf) {
			data->tx_buf_size = 0;
			retval = -ENOMEM;
			goto exit;
		}
	}
	data->tx_buf[0] = commandcode & 0xff;
	memcpy(data->tx_buf + 1, buf, len);

	if (COMMS_DEBUG(data) &&
			!copy_to_debug_buf(&client->dev, data, buf, len))
		dev_dbg(&client->dev, "writes command %#04x %d bytes:%s\n",
			commandcode, len, data->debug_buf);

	phys->info.tx_count++;
	phys->info.tx_bytes += tx_size;

	retval = i2c_smbus_write_block_data(client, commandcode,
					    tx_size, data->tx_buf);
	if (retval < 0)
		phys->info.tx_errs++;

	return retval;
}
示例#5
0
/*SMB version 2 block read - wrapper over ic2_smb_read_block */
static int smb_v2_block_read(struct rmi_phys_device *phys,
			u8 commandcode, u8 *buf, int len)
{
	struct i2c_client *client = to_i2c_client(phys->dev);
	struct rmi_smb_data *data = phys->data;
	int retval;

/*	mutex_lock(&data->page_mutex); */

	retval = i2c_smbus_read_block_data(client, commandcode, buf);
	phys->info.rx_count++;
	phys->info.rx_bytes += len;
	if (retval < 0) {
		phys->info.rx_errs++;
		return retval;
	} else if (COMMS_DEBUG(data) &&
			!copy_to_debug_buf(&client->dev, data, buf, len))
		dev_dbg(&client->dev, "read %d bytes for command %#04x:%s\n",
			len, commandcode, data->debug_buf);

/*	mutex_unlock(&data->page_mutex);	*/
	return retval;
}
示例#6
0
static int rmi_hid_read_block(struct rmi_transport_device *xport, u16 addr,
			      void *buf, const int len)
{
        struct hid_device *hdev = to_hid_device(xport->dev);
	struct rmi_hid_data *data = xport->data;
	int ret;
	int bytes_read;
	int bytes_needed;
	int retries;
	int read_input_count;

	mutex_lock(&data->page_mutex);

	if (RMI_HID_PAGE(addr) != data->page) {
		ret = rmi_set_page(xport, RMI_HID_PAGE(addr));
		if (ret < 0)
			goto exit;
	}

	for (retries = 5; retries > 0; retries--) {
		data->writeReport[RMI_HID_REPORT_ID] = RMI_READ_ADDR_REPORT_ID;
		data->writeReport[1] = 0; /* old 1 byte read count */
		data->writeReport[RMI_HID_READ_OUTPUT_ADDR] = addr & 0xFF;
		data->writeReport[RMI_HID_READ_OUTPUT_ADDR + 1] = (addr >> 8) & 0xFF;
		data->writeReport[RMI_HID_READ_OUTPUT_COUNT] = len  & 0xFF;
		data->writeReport[RMI_HID_READ_OUTPUT_COUNT + 1] = (len >> 8) & 0xFF;

		if (COMMS_DEBUG(data)) {
			ret = copy_to_debug_buf(&hdev->dev, data, data->writeReport, len);
			if (!ret)
				dev_dbg(&hdev->dev, "wrote %d bytes at %#06x:%s\n",
					len, addr, data->debug_buf);
		}

		set_bit(RMI_HID_READ_REQUEST_PENDING, &data->flags);

		ret = rmi_hid_write_report(hdev, data->writeReport,
						data->output_report_size);
		if (ret != data->output_report_size) {
			clear_bit(RMI_HID_READ_REQUEST_PENDING, &data->flags);
			dev_err(&hdev->dev,
				"failed to write request output report (%d)\n", ret);
			goto exit;
		}

		bytes_read = 0;
		bytes_needed = len;
		while (bytes_read < len) {
			if (!wait_event_timeout(data->wait, 
					test_bit(RMI_HID_READ_DATA_PENDING, &data->flags),
					msecs_to_jiffies(1000)))
			{
					dev_info(&hdev->dev, "%s: timeout elapsed\n", __func__);
					ret = -ENODATA;
					break;
			} else {
				if (data->readReport[RMI_HID_REPORT_ID]
						!= RMI_READ_DATA_REPORT_ID)
				{
					ret = -ENODATA;
					dev_err(&hdev->dev,
						"%s: Expected data report, but got"
						" report id %d instead", __func__,
						data->readReport[RMI_HID_REPORT_ID]);
					goto exit;
				}

				read_input_count = data->readReport[RMI_HID_READ_INPUT_COUNT];
				memcpy(buf + bytes_read,
					&data->readReport[RMI_HID_READ_INPUT_DATA],
					read_input_count < bytes_needed 
					? read_input_count : bytes_needed);

				if (COMMS_DEBUG(data)) {
					ret = copy_to_debug_buf(&hdev->dev, data,
							(u8 *) buf + bytes_read,
							read_input_count);
					if (!ret)
						dev_dbg(&hdev->dev, "read %d bytes at %#06x:%s\n",
							read_input_count, addr,
							data->debug_buf);
				}
				bytes_read += read_input_count;
				bytes_needed -= read_input_count;
				clear_bit(RMI_HID_READ_DATA_PENDING, &data->flags);
			}
		}

		if (bytes_read == len)
			break;
	}

	if (bytes_read == len) {
		xport->info.rx_count++;
		xport->info.rx_bytes += len;
		ret = len;
	}

exit:
	clear_bit(RMI_HID_READ_REQUEST_PENDING, &data->flags);
	mutex_unlock(&data->page_mutex);
	return ret;
}