drivers/media/rc/xbox_remote.c

Source file repositories/reference/linux-study-clean/drivers/media/rc/xbox_remote.c

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/xbox_remote.c
Extension
.c
Size
8152 bytes
Lines
313
Domain
Driver Families
Bucket
drivers/media
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

struct xbox_remote {
	struct rc_dev *rdev;
	struct usb_device *udev;
	struct usb_interface *interface;

	struct urb *irq_urb;
	u8 *inbuf;

	char rc_name[NAME_BUFSIZE];
	char rc_phys[NAME_BUFSIZE];
};

static int xbox_remote_rc_open(struct rc_dev *rdev)
{
	struct xbox_remote *xbox_remote = rdev->priv;

	/* On first open, submit the read urb which was set up previously. */
	xbox_remote->irq_urb->dev = xbox_remote->udev;
	if (usb_submit_urb(xbox_remote->irq_urb, GFP_KERNEL)) {
		dev_err(&xbox_remote->interface->dev,
			"%s: usb_submit_urb failed!\n", __func__);
		return -EIO;
	}

	return 0;
}

static void xbox_remote_rc_close(struct rc_dev *rdev)
{
	struct xbox_remote *xbox_remote = rdev->priv;

	usb_kill_urb(xbox_remote->irq_urb);
}

/*
 * xbox_remote_report_input
 */
static void xbox_remote_input_report(struct urb *urb)
{
	struct xbox_remote *xbox_remote = urb->context;
	unsigned char *data = xbox_remote->inbuf;

	/*
	 * data[0] = 0x00
	 * data[1] = length - always 0x06
	 * data[2] = the key code
	 * data[3] = high part of key code
	 * data[4] = last_press_ms (low)
	 * data[5] = last_press_ms (high)
	 */

	/* Deal with strange looking inputs */
	if (urb->actual_length != 6 || urb->actual_length != data[1]) {
		dev_warn(&urb->dev->dev, "Weird data, len=%d: %*ph\n",
			 urb->actual_length, urb->actual_length, data);
		return;
	}

	rc_keydown(xbox_remote->rdev, RC_PROTO_XBOX_DVD,
		   le16_to_cpup((__le16 *)(data + 2)), 0);
}

/*
 * xbox_remote_irq_in
 */
static void xbox_remote_irq_in(struct urb *urb)
{
	struct xbox_remote *xbox_remote = urb->context;
	int retval;

	switch (urb->status) {
	case 0:			/* success */
		xbox_remote_input_report(urb);
		break;
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
	case -ESHUTDOWN:
		dev_dbg(&xbox_remote->interface->dev,
			"%s: urb error status, unlink?\n",
			__func__);
		return;
	default:		/* error */
		dev_dbg(&xbox_remote->interface->dev,
			"%s: Nonzero urb status %d\n",
			__func__, urb->status);
	}

	retval = usb_submit_urb(urb, GFP_ATOMIC);
	if (retval)
		dev_err(&xbox_remote->interface->dev,

Annotation

Implementation Notes