@@ -597,9 +597,8 @@ struct sony_sc {
/* DS4 calibration data */
struct ds4_calibration_data ds4_calib_data[6];
/* GH Live */
+ struct urb *ghl_urb;
struct timer_list ghl_poke_timer;
- struct usb_ctrlrequest *ghl_cr;
- u8 *ghl_databuf;
};
static void sony_set_leds(struct sony_sc *sc);
@@ -625,66 +624,54 @@ static inline void sony_schedule_work(struct sony_sc *sc,
static void ghl_magic_poke_cb(struct urb *urb)
{
- if (urb) {
- /* Free sc->ghl_cr and sc->ghl_databuf allocated in
- * ghl_magic_poke()
- */
- kfree(urb->setup_packet);
- kfree(urb->transfer_buffer);
- }
+ struct sony_sc *sc = urb->context;
+
+ if (urb->status < 0)
+ hid_err(sc->hdev, "URB transfer failed : %d", urb->status);
+
+ mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
}
static void ghl_magic_poke(struct timer_list *t)
{
+ int ret;
struct sony_sc *sc = from_timer(sc, t, ghl_poke_timer);
- int ret;
+ ret = usb_submit_urb(sc->ghl_urb, GFP_ATOMIC);
+ if (ret < 0)
+ hid_err(sc->hdev, "usb_submit_urb failed: %d", ret);
+}
+
+static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev)
+{
+ struct usb_ctrlrequest *cr;
+ u16 poke_size;
+ u8 *databuf;
unsigned int pipe;
- struct urb *urb;
- struct usb_device *usbdev = to_usb_device(sc->hdev->dev.parent->parent);
- const u16 poke_size =
- ARRAY_SIZE(ghl_ps3wiiu_magic_data);
+ poke_size = ARRAY_SIZE(ghl_ps3wiiu_magic_data);
pipe = usb_sndctrlpipe(usbdev, 0);
- if (!sc->ghl_cr) {
- sc->ghl_cr = kzalloc(sizeof(*sc->ghl_cr), GFP_ATOMIC);
- if (!sc->ghl_cr)
- goto resched;
- }
-
- if (!sc->ghl_databuf) {
- sc->ghl_databuf = kzalloc(poke_size, GFP_ATOMIC);
- if (!sc->ghl_databuf)
- goto resched;
- }
+ cr = devm_kzalloc(&sc->hdev->dev, sizeof(*cr), GFP_ATOMIC);
+ if (cr == NULL)
+ return -ENOMEM;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb)
- goto resched;
+ databuf = devm_kzalloc(&sc->hdev->dev, poke_size, GFP_ATOMIC);
+ if (databuf == NULL)
+ return -ENOMEM;
- sc->ghl_cr->bRequestType =
+ cr->bRequestType =
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT;
- sc->ghl_cr->bRequest = USB_REQ_SET_CONFIGURATION;
- sc->ghl_cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value);
- sc->ghl_cr->wIndex = 0;
- sc->ghl_cr->wLength = cpu_to_le16(poke_size);
- memcpy(sc->ghl_databuf, ghl_ps3wiiu_magic_data, poke_size);
-
+ cr->bRequest = USB_REQ_SET_CONFIGURATION;
+ cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value);
+ cr->wIndex = 0;
+ cr->wLength = cpu_to_le16(poke_size);
+ memcpy(databuf, ghl_ps3wiiu_magic_data, poke_size);
usb_fill_control_urb(
- urb, usbdev, pipe,
- (unsigned char *) sc->ghl_cr, sc->ghl_databuf,
- poke_size, ghl_magic_poke_cb, NULL);
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret < 0) {
- kfree(sc->ghl_databuf);
- kfree(sc->ghl_cr);
- }
- usb_free_urb(urb);
-
-resched:
- /* Reschedule for next time */
- mod_timer(&sc->ghl_poke_timer, jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
+ sc->ghl_urb, usbdev, pipe,
+ (unsigned char *) cr, databuf, poke_size,
+ ghl_magic_poke_cb, sc);
+ return 0;
}
static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -2981,6 +2968,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
int ret;
unsigned long quirks = id->driver_data;
struct sony_sc *sc;
+ struct usb_device *usbdev;
unsigned int connect_mask = HID_CONNECT_DEFAULT;
if (!strcmp(hdev->name, "FutureMax Dance Mat"))
@@ -3000,6 +2988,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
sc->quirks = quirks;
hid_set_drvdata(hdev, sc);
sc->hdev = hdev;
+ usbdev = to_usb_device(sc->hdev->dev.parent->parent);
ret = hid_parse(hdev);
if (ret) {
@@ -3042,6 +3031,15 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
if (sc->quirks & GHL_GUITAR_PS3WIIU) {
+ sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!sc->ghl_urb)
+ return -ENOMEM;
+ ret = ghl_init_urb(sc, usbdev);
+ if (ret) {
+ hid_err(hdev, "error preparing URB\n");
+ return ret;
+ }
+
timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0);
mod_timer(&sc->ghl_poke_timer,
jiffies + GHL_GUITAR_POKE_INTERVAL*HZ);
@@ -3054,8 +3052,10 @@ static void sony_remove(struct hid_device *hdev)
{
struct sony_sc *sc = hid_get_drvdata(hdev);
- if (sc->quirks & GHL_GUITAR_PS3WIIU)
+ if (sc->quirks & GHL_GUITAR_PS3WIIU) {
del_timer_sync(&sc->ghl_poke_timer);
+ usb_free_urb(sc->ghl_urb);
+ }
hid_hw_close(hdev);