^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Driver for Xbox DVD Movie Playback Kit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2018 by Benjamin Valentin <benpicco@googlemail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Xbox DVD Movie Playback Kit USB IR dongle support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * The driver was derived from the ati_remote driver 2.2.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * and used information from lirc_xbox.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (c) 2011, 2012 Anssi Hannula <anssi.hannula@iki.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (c) 2002 Vladimir Dergachev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (c) 2003-2004 Paul Miller <pmiller9@users.sourceforge.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/usb/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/rc-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Module and Version Information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define DRIVER_VERSION "1.0.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DRIVER_AUTHOR "Benjamin Valentin <benpicco@googlemail.com>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DRIVER_DESC "Xbox DVD USB Remote Control"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define NAME_BUFSIZE 80 /* size of product name, path buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DATA_BUFSIZE 8 /* size of URB data buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * USB vendor ids for XBOX DVD Dongles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define VENDOR_GAMESTER 0x040b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define VENDOR_MICROSOFT 0x045e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static const struct usb_device_id xbox_remote_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Gamester Xbox DVD Movie Playback Kit IR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) USB_DEVICE(VENDOR_GAMESTER, 0x6521),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Microsoft Xbox DVD Movie Playback Kit IR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) USB_DEVICE(VENDOR_MICROSOFT, 0x0284),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {} /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_DEVICE_TABLE(usb, xbox_remote_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct xbox_remote {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct rc_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct usb_device *udev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct usb_interface *interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct urb *irq_urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned char inbuf[DATA_BUFSIZE] __aligned(sizeof(u16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) char rc_name[NAME_BUFSIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char rc_phys[NAME_BUFSIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int xbox_remote_rc_open(struct rc_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct xbox_remote *xbox_remote = rdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* On first open, submit the read urb which was set up previously. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) xbox_remote->irq_urb->dev = xbox_remote->udev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (usb_submit_urb(xbox_remote->irq_urb, GFP_KERNEL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) dev_err(&xbox_remote->interface->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "%s: usb_submit_urb failed!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void xbox_remote_rc_close(struct rc_dev *rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct xbox_remote *xbox_remote = rdev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) usb_kill_urb(xbox_remote->irq_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * xbox_remote_report_input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void xbox_remote_input_report(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct xbox_remote *xbox_remote = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned char *data = xbox_remote->inbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * data[0] = 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * data[1] = length - always 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * data[2] = the key code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * data[3] = high part of key code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * data[4] = last_press_ms (low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * data[5] = last_press_ms (high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Deal with strange looking inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (urb->actual_length != 6 || urb->actual_length != data[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) dev_warn(&urb->dev->dev, "Weird data, len=%d: %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) urb->actual_length, urb->actual_length, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) rc_keydown(xbox_remote->rdev, RC_PROTO_XBOX_DVD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) le16_to_cpup((__le16 *)(data + 2)), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * xbox_remote_irq_in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void xbox_remote_irq_in(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct xbox_remote *xbox_remote = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) switch (urb->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case 0: /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) xbox_remote_input_report(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case -ECONNRESET: /* unlink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) dev_dbg(&xbox_remote->interface->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) "%s: urb error status, unlink?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) default: /* error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dev_dbg(&xbox_remote->interface->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) "%s: Nonzero urb status %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) __func__, urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) retval = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_err(&xbox_remote->interface->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) "%s: usb_submit_urb()=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) __func__, retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void xbox_remote_rc_init(struct xbox_remote *xbox_remote)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct rc_dev *rdev = xbox_remote->rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) rdev->priv = xbox_remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) rdev->allowed_protocols = RC_PROTO_BIT_XBOX_DVD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rdev->driver_name = "xbox_remote";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rdev->open = xbox_remote_rc_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rdev->close = xbox_remote_rc_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) rdev->device_name = xbox_remote->rc_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) rdev->input_phys = xbox_remote->rc_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) rdev->timeout = MS_TO_US(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) usb_to_input_id(xbox_remote->udev, &rdev->input_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) rdev->dev.parent = &xbox_remote->interface->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int xbox_remote_initialize(struct xbox_remote *xbox_remote,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct usb_endpoint_descriptor *endpoint_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct usb_device *udev = xbox_remote->udev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int pipe, maxp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* Set up irq_urb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pipe = usb_rcvintpipe(udev, endpoint_in->bEndpointAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) usb_fill_int_urb(xbox_remote->irq_urb, udev, pipe, xbox_remote->inbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) maxp, xbox_remote_irq_in, xbox_remote,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) endpoint_in->bInterval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * xbox_remote_probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int xbox_remote_probe(struct usb_interface *interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct usb_device *udev = interface_to_usbdev(interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct usb_host_interface *iface_host = interface->cur_altsetting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct usb_endpoint_descriptor *endpoint_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct xbox_remote *xbox_remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct rc_dev *rc_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) // why is there also a device with no endpoints?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (iface_host->desc.bNumEndpoints == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (iface_host->desc.bNumEndpoints != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pr_err("%s: Unexpected desc.bNumEndpoints: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) __func__, iface_host->desc.bNumEndpoints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) endpoint_in = &iface_host->endpoint[0].desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!usb_endpoint_is_int_in(endpoint_in)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) pr_err("%s: Unexpected endpoint_in\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) pr_err("%s: endpoint_in message size==0?\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) xbox_remote = kzalloc(sizeof(*xbox_remote), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!xbox_remote || !rc_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto exit_free_dev_rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* Allocate URB buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) xbox_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!xbox_remote->irq_urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) goto exit_free_buffers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) xbox_remote->udev = udev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) xbox_remote->rdev = rc_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) xbox_remote->interface = interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) usb_make_path(udev, xbox_remote->rc_phys, sizeof(xbox_remote->rc_phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) strlcat(xbox_remote->rc_phys, "/input0", sizeof(xbox_remote->rc_phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) snprintf(xbox_remote->rc_name, sizeof(xbox_remote->rc_name), "%s%s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) udev->manufacturer ?: "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) udev->manufacturer && udev->product ? " " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) udev->product ?: "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (!strlen(xbox_remote->rc_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) snprintf(xbox_remote->rc_name, sizeof(xbox_remote->rc_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) DRIVER_DESC "(%04x,%04x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) le16_to_cpu(xbox_remote->udev->descriptor.idVendor),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) le16_to_cpu(xbox_remote->udev->descriptor.idProduct));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rc_dev->map_name = RC_MAP_XBOX_DVD; /* default map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) xbox_remote_rc_init(xbox_remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* Device Hardware Initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) err = xbox_remote_initialize(xbox_remote, endpoint_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) goto exit_kill_urbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Set up and register rc device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) err = rc_register_device(xbox_remote->rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) goto exit_kill_urbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) usb_set_intfdata(interface, xbox_remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) exit_kill_urbs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) usb_kill_urb(xbox_remote->irq_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) exit_free_buffers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) usb_free_urb(xbox_remote->irq_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) exit_free_dev_rdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) rc_free_device(rc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) kfree(xbox_remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * xbox_remote_disconnect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static void xbox_remote_disconnect(struct usb_interface *interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct xbox_remote *xbox_remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) xbox_remote = usb_get_intfdata(interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) usb_set_intfdata(interface, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!xbox_remote) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dev_warn(&interface->dev, "%s - null device?\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) usb_kill_urb(xbox_remote->irq_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) rc_unregister_device(xbox_remote->rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) usb_free_urb(xbox_remote->irq_urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) kfree(xbox_remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /* usb specific object to register with the usb subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static struct usb_driver xbox_remote_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .name = "xbox_remote",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .probe = xbox_remote_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .disconnect = xbox_remote_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .id_table = xbox_remote_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) module_usb_driver(xbox_remote_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) MODULE_AUTHOR(DRIVER_AUTHOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) MODULE_LICENSE("GPL");