drivers/hid/amd-sfh-hid/amd_sfh_client.c

Source file repositories/reference/linux-study-clean/drivers/hid/amd-sfh-hid/amd_sfh_client.c

File Facts

System
Linux kernel
Corpus path
drivers/hid/amd-sfh-hid/amd_sfh_client.c
Extension
.c
Size
11730 bytes
Lines
386
Domain
Driver Families
Bucket
drivers/hid
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 (cli_data->hid_sensor_hubs[i] == hid) {
			cli_data->cur_hid_dev = i;
			break;
		}
	}
	amdtp_hid_wakeup(hid);
}

int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
{
	struct amdtp_hid_data *hid_data = hid->driver_data;
	struct amdtp_cl_data *cli_data = hid_data->cli_data;
	struct request_list *req_list = &cli_data->req_list;
	struct amd_input_data *in_data = cli_data->in_data;
	struct amd_mp2_dev *mp2;
	int i;

	mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
	guard(mutex)(&mp2->lock);
	for (i = 0; i < cli_data->num_hid_devices; i++) {
		if (cli_data->hid_sensor_hubs[i] == hid) {
			struct request_list *new = kzalloc_obj(*new);

			if (!new)
				return -ENOMEM;

			new->current_index = i;
			new->sensor_idx = cli_data->sensor_idx[i];
			new->hid = hid;
			new->report_type = report_type;
			new->report_id = report_id;
			cli_data->report_id[i] = report_id;
			cli_data->request_done[i] = false;
			list_add(&new->list, &req_list->list);
			break;
		}
	}
	schedule_delayed_work(&cli_data->work, 0);
	return 0;
}

void amd_sfh_work(struct work_struct *work)
{
	struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
	struct request_list *req_list = &cli_data->req_list;
	struct amd_input_data *in_data = cli_data->in_data;
	struct request_list *req_node;
	u8 current_index, sensor_index;
	struct amd_mp2_ops *mp2_ops;
	struct amd_mp2_dev *mp2;
	u8 report_id, node_type;
	u8 report_size = 0;

	mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
	guard(mutex)(&mp2->lock);
	req_node = list_last_entry(&req_list->list, struct request_list, list);
	list_del(&req_node->list);
	current_index = req_node->current_index;
	sensor_index = req_node->sensor_idx;
	report_id = req_node->report_id;
	node_type = req_node->report_type;
	kfree(req_node);

	mp2_ops = mp2->mp2_ops;
	if (node_type == HID_FEATURE_REPORT) {
		report_size = mp2_ops->get_feat_rep(sensor_index, report_id,
						    cli_data->feature_report[current_index]);
		if (report_size)
			hid_input_report(cli_data->hid_sensor_hubs[current_index],
					 cli_data->report_type[current_index],
					 cli_data->feature_report[current_index], report_size, 0);
		else
			pr_err("AMDSFH: Invalid report size\n");

	} else if (node_type == HID_INPUT_REPORT) {
		report_size = mp2_ops->get_in_rep(current_index, sensor_index, report_id, in_data);
		if (report_size)
			hid_input_report(cli_data->hid_sensor_hubs[current_index],
					 cli_data->report_type[current_index],
					 in_data->input_report[current_index], report_size, 0);
		else
			pr_err("AMDSFH: Invalid report size\n");
	}
	cli_data->cur_hid_dev = current_index;
	cli_data->sensor_requested_cnt[current_index] = 0;
	amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]);
	if (!list_empty(&req_list->list))
		schedule_delayed_work(&cli_data->work, 0);
}

Annotation

Implementation Notes