From patchwork Mon May 3 20:15:56 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Ospite X-Patchwork-Id: 96552 X-Patchwork-Delegate: jikos@jikos.cz Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o43KG8p8029047 for ; Mon, 3 May 2010 20:16:08 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756725Ab0ECUQH (ORCPT ); Mon, 3 May 2010 16:16:07 -0400 Received: from smtp-out19.alice.it ([85.33.2.19]:2788 "EHLO smtp-out19.alice.it" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756535Ab0ECUQG (ORCPT ); Mon, 3 May 2010 16:16:06 -0400 Received: from FBCMMO02.fbc.local ([192.168.68.196]) by smtp-out19.alice.it with Microsoft SMTPSVC(6.0.3790.3959); Mon, 3 May 2010 22:16:02 +0200 Received: from FBCMCL01B03.fbc.local ([192.168.69.84]) by FBCMMO02.fbc.local with Microsoft SMTPSVC(6.0.3790.3959); Mon, 3 May 2010 22:16:02 +0200 Received: from jcn ([82.61.86.179]) by FBCMCL01B03.fbc.local with Microsoft SMTPSVC(6.0.3790.3959); Mon, 3 May 2010 22:16:00 +0200 Received: from ao2 by jcn with local (Exim 4.71) (envelope-from ) id 1O923b-00086R-B5; Mon, 03 May 2010 22:15:59 +0200 From: Antonio Ospite To: linux-input@vger.kernel.org Cc: Antonio Ospite , Bastien Nocera , linux-bluetooth@vger.kernel.org, cbe-oss-dev@lists.ozlabs.org Subject: [PATCH 2/2] hid/hid-sony: get and set Sixaxis bdaddr via sysfs Date: Mon, 3 May 2010 22:15:56 +0200 Message-Id: <1272917756-31098-3-git-send-email-ospite@studenti.unina.it> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1272917756-31098-1-git-send-email-ospite@studenti.unina.it> References: <1272917756-31098-1-git-send-email-ospite@studenti.unina.it> X-Face: z*RaLf`X<@C75u6Ig9}{oW$H; 1_\2t5)({*|jhM/Vb; ]yA5\I~93>J<_`<4)A{':UrE X-OriginalArrivalTime: 03 May 2010 20:16:01.0096 (UTC) FILETIME=[73073C80:01CAEAFD] Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 03 May 2010 20:16:09 +0000 (UTC) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index d61f268..1b611ec 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -47,6 +47,131 @@ static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, } /* + * Show and set the master bdaddr for PS3 controller, without disconnecting + * the device. + */ +static ssize_t show_sixaxis_master_bdaddr(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_device *udev = interface_to_usbdev(intf); + __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + int ret; + unsigned char *mbuf = kmalloc(9, GFP_KERNEL); + + if (!mbuf) + return -ENOMEM; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + HID_REQ_GET_REPORT, + USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, + (3 << 8) | 0xf5, ifnum, mbuf, 8, + USB_CTRL_GET_TIMEOUT); + if (ret < 0) + dev_err(dev, "%s failed to get master bdaddr, ret: %d\n", + __func__, ret); + else + /* 18 is strlen("00:00:00:00:00:00\n") */ + ret = snprintf(buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x\n", + mbuf[2], mbuf[3], mbuf[4], + mbuf[5], mbuf[6], mbuf[7]); + + kfree(mbuf); + + return ret; +} + +static ssize_t store_sixaxis_master_bdaddr(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_device *udev = interface_to_usbdev(intf); + __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + int ret; + unsigned char *mbuf = kmalloc(9, GFP_KERNEL); + + mbuf[0] = 0x01; + mbuf[1] = 0x00; + ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &mbuf[2], &mbuf[3], &mbuf[4], + &mbuf[5], &mbuf[6], &mbuf[7]); + if (ret != 6) { + dev_err(dev, "%s failed, ret: %d\n", __func__, ret); + return -EINVAL; + } + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + HID_REQ_SET_REPORT, + USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, + (3 << 8) | 0xf5, ifnum, mbuf, 8, + USB_CTRL_GET_TIMEOUT); + + kfree(mbuf); + + if (ret < 0) { + dev_err(dev, "%s failed to set master bdaddr, ret: %d\n", + __func__, ret); + return ret; + } + + return count; +} + +/* + * Show the bdaddr for PS3 controller, without disconnecting the device. + */ +static ssize_t show_sixaxis_bdaddr(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_device *udev = interface_to_usbdev(intf); + __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + int ret; + unsigned char *mbuf = kmalloc(18, GFP_KERNEL); + + if (!mbuf) + return -ENOMEM; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + HID_REQ_GET_REPORT, + USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, + (3 << 8) | 0xf2, ifnum, mbuf, 17, + USB_CTRL_GET_TIMEOUT); + if (ret < 0) + dev_err(dev, "%s failed to get device bdaddr, ret: %d\n", + __func__, ret); + else + /* 18 is strlen("00:00:00:00:00:00\n") */ + ret = snprintf(buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x\n", + mbuf[4], mbuf[5], mbuf[6], + mbuf[7], mbuf[8], mbuf[9]); + + kfree(mbuf); + + return ret; +} + +static DEVICE_ATTR(sixaxis_master_bdaddr, S_IWUSR|S_IRUGO, + show_sixaxis_master_bdaddr, store_sixaxis_master_bdaddr); + +static DEVICE_ATTR(sixaxis_bdaddr, S_IRUGO, + show_sixaxis_bdaddr, NULL); + +static struct attribute *sixaxis_attributes[] = { + &dev_attr_sixaxis_master_bdaddr.attr, + &dev_attr_sixaxis_bdaddr.attr, + NULL +}; + +static const struct attribute_group sixaxis_attr_group = { + .attrs = sixaxis_attributes, +}; + + +/* * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller * to "operational". Without this, the ps3 controller will not report any * events. @@ -57,8 +182,9 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) struct usb_device *dev = interface_to_usbdev(intf); __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; int ret; - char *buf = kmalloc(18, GFP_KERNEL); + unsigned char *buf = kmalloc(18, GFP_KERNEL); + dev_info(&hdev->dev, "Calling %s\n", __func__); if (!buf) return -ENOMEM; @@ -70,6 +196,9 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) USB_CTRL_GET_TIMEOUT); if (ret < 0) dev_err(&hdev->dev, "can't set operational mode\n"); + else + dev_info(&hdev->dev, "Sony PS3 Controller bdaddr: %02x:%02x:%02x:%02x:%02x:%02x\n", + buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]); kfree(buf); @@ -110,9 +239,17 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err_free; } - if (sc->quirks & SIXAXIS_CONTROLLER_USB) + if (sc->quirks & SIXAXIS_CONTROLLER_USB) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + ret = sysfs_create_group(&intf->dev.kobj, &sixaxis_attr_group); + if (ret < 0) { + dev_err(&hdev->dev, + "cannot register sixaxis sysfs hooks\n"); + goto err_stop; + } + ret = sixaxis_set_operational_usb(hdev); - else if (sc->quirks & SIXAXIS_CONTROLLER_BT) + } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ret = sixaxis_set_operational_bt(hdev); else ret = 0; @@ -130,6 +267,11 @@ err_free: static void sony_remove(struct hid_device *hdev) { + struct sony_sc *sc = hid_get_drvdata(hdev); + if (sc->quirks & SIXAXIS_CONTROLLER_USB) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + sysfs_remove_group(&intf->dev.kobj, &sixaxis_attr_group); + } hid_hw_stop(hdev); kfree(hid_get_drvdata(hdev)); }