drivers/hid/surface-hid/surface_hid.c
Source file repositories/reference/linux-study-clean/drivers/hid/surface-hid/surface_hid.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/hid/surface-hid/surface_hid.c- Extension
.c- Size
- 6969 bytes
- Lines
- 254
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/unaligned.hlinux/hid.hlinux/kernel.hlinux/module.hlinux/types.hlinux/surface_aggregator/controller.hlinux/surface_aggregator/device.hsurface_hid_core.h
Detected Declarations
struct surface_hid_buffer_sliceenum surface_hid_cidfunction ssam_hid_get_descriptorfunction ssam_hid_set_raw_reportfunction ssam_hid_get_raw_reportfunction ssam_hid_event_fnfunction shid_output_reportfunction shid_get_feature_reportfunction shid_set_feature_reportfunction surface_hid_probefunction surface_hid_remove
Annotated Snippet
struct surface_hid_buffer_slice {
__u8 entry;
__le32 offset;
__le32 length;
__u8 end;
__u8 data[];
} __packed;
static_assert(sizeof(struct surface_hid_buffer_slice) == 10);
enum surface_hid_cid {
SURFACE_HID_CID_OUTPUT_REPORT = 0x01,
SURFACE_HID_CID_GET_FEATURE_REPORT = 0x02,
SURFACE_HID_CID_SET_FEATURE_REPORT = 0x03,
SURFACE_HID_CID_GET_DESCRIPTOR = 0x04,
};
static int ssam_hid_get_descriptor(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len)
{
u8 buffer[sizeof(struct surface_hid_buffer_slice) + 0x76];
struct surface_hid_buffer_slice *slice;
struct ssam_request rqst;
struct ssam_response rsp;
u32 buffer_len, offset, length;
int status;
/*
* Note: The 0x76 above has been chosen because that's what's used by
* the Windows driver. Together with the header, this leads to a 128
* byte payload in total.
*/
buffer_len = ARRAY_SIZE(buffer) - sizeof(struct surface_hid_buffer_slice);
rqst.target_category = shid->uid.category;
rqst.target_id = shid->uid.target;
rqst.command_id = SURFACE_HID_CID_GET_DESCRIPTOR;
rqst.instance_id = shid->uid.instance;
rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
rqst.length = sizeof(struct surface_hid_buffer_slice);
rqst.payload = buffer;
rsp.capacity = ARRAY_SIZE(buffer);
rsp.pointer = buffer;
slice = (struct surface_hid_buffer_slice *)buffer;
slice->entry = entry;
slice->end = 0;
offset = 0;
length = buffer_len;
while (!slice->end && offset < len) {
put_unaligned_le32(offset, &slice->offset);
put_unaligned_le32(length, &slice->length);
rsp.length = 0;
status = ssam_retry(ssam_request_do_sync_onstack, shid->ctrl, &rqst, &rsp,
sizeof(*slice));
if (status)
return status;
offset = get_unaligned_le32(&slice->offset);
length = get_unaligned_le32(&slice->length);
/* Don't mess stuff up in case we receive garbage. */
if (length > buffer_len || offset > len)
return -EPROTO;
if (offset + length > len)
length = len - offset;
memcpy(buf + offset, &slice->data[0], length);
offset += length;
length = buffer_len;
}
if (offset != len) {
dev_err(shid->dev, "unexpected descriptor length: got %u, expected %zu\n",
offset, len);
return -EPROTO;
}
return 0;
}
static int ssam_hid_set_raw_report(struct surface_hid_device *shid, u8 rprt_id, bool feature,
u8 *buf, size_t len)
Annotation
- Immediate include surface: `linux/unaligned.h`, `linux/hid.h`, `linux/kernel.h`, `linux/module.h`, `linux/types.h`, `linux/surface_aggregator/controller.h`, `linux/surface_aggregator/device.h`, `surface_hid_core.h`.
- Detected declarations: `struct surface_hid_buffer_slice`, `enum surface_hid_cid`, `function ssam_hid_get_descriptor`, `function ssam_hid_set_raw_report`, `function ssam_hid_get_raw_report`, `function ssam_hid_event_fn`, `function shid_output_report`, `function shid_get_feature_report`, `function shid_set_feature_report`, `function surface_hid_probe`.
- Atlas domain: Driver Families / drivers/hid.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.