Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp6557969ybc; Thu, 28 Nov 2019 01:18:24 -0800 (PST) X-Google-Smtp-Source: APXvYqyCS4O1h32OjB7T9ZiPwaYZ1Mkl1uqHZTeVNHghvlSK7XDnHKlfzVbGXTc9DKFem79ZCje7 X-Received: by 2002:aa7:c54a:: with SMTP id s10mr31197777edr.5.1574932704766; Thu, 28 Nov 2019 01:18:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574932704; cv=none; d=google.com; s=arc-20160816; b=wpFNKQPYksapXjF3UDQml1aGkdsRDKuj26xswS8y+tdI5ec7xRkbLc36+MUuwwm21x XflV4z80azhm0DcDHb3/xQZ+E6hkDfwRxHE6QIYeIz6XPxP/x0JAezMtORWaYWXmepbM 07Y8hs6LpYgH/0N0C3RclSo2Pr1VcJwd9P/51ISdDw18AVqb+2HST5ZuNbuqoREE9aCY MaZw/oPVvikILAvgJrNkUcWvALg3d7q9jT+HP1Qxj3tekDnXt6J7g1avPZ60NOUN1TnJ 8FC9GjmxH7szSiqdj5iedk3ejPloVv5D/2aKYF9crXTPaJqMf85jgYVUMpbjIhcCyTs6 mf9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=PdWj7QB3fbaugHtf7HeLJsrCDfrHnvltk3csO4s4rNA=; b=L8D44yIIzGWKrVtguajqs9cKHHEZYQWPRHewalU1GML7FYDEvo92WptnvHLSMJ9vXN 2q1rqs1vL+XQeAgESwrIODcQqyVoaTQvuOZncg6yD/5aokEq+nxTlmSvKxpRMeyD+K8g f72WnQvSoyZyddqlo9k5B+jSm+qg8IhqwofCasz0vbHLTZAoLLTvarzuYvNdd+gSmEK3 DDJDxDaQJyXlq2K6l2Jft43SI/8QUKzrvL54X6aJnfgXcPaIfNitIcP40OQX/xj+rPJU 3D7ROU8MMxWFLEov5mHDjU1iMvDWy7usrBJwvDOhLM3OX3VmlbBA2qtlm4sveN11tXQq aajA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=e2DemXfN; spf=pass (google.com: best guess record for domain of linux-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e19si11272442ejb.379.2019.11.28.01.17.59; Thu, 28 Nov 2019 01:18:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=e2DemXfN; spf=pass (google.com: best guess record for domain of linux-bluetooth-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726670AbfK1JRr (ORCPT + 99 others); Thu, 28 Nov 2019 04:17:47 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:44747 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726252AbfK1JRr (ORCPT ); Thu, 28 Nov 2019 04:17:47 -0500 Received: by mail-pl1-f195.google.com with SMTP id az9so11322438plb.11 for ; Thu, 28 Nov 2019 01:17:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=PdWj7QB3fbaugHtf7HeLJsrCDfrHnvltk3csO4s4rNA=; b=e2DemXfNWMxuk7L4hV4cq21v6Ep9Ym9m/HNZBJdwKf0qHoQp/kSduEQBBSk/K1S3tm 0+Kog4ikBYWbIYlJdmfvMx5Hy/4aRrP5GYIOrNnfLrSx80LVQSh3Y54+QM6ypmGPvqYm GlaMx+Gio1u5f2q+EqcrlsZCQCx3pJ37HgiEKKOnq8erV1Rbli1KgQWtGi4VnxNofmIk 4Xue0qi985g1slRWoCtoJz04mFkZCtydcHbb2JRSVRPcAXB0ufjnsxn0kT6dTKkvTDMz mW9UvgexZm0gDntv3l6MMQI7/W9bSTVBwVX0E1Tfcr0TwkdBkJBZx7fzHYl5qtIDIzvQ HW+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=PdWj7QB3fbaugHtf7HeLJsrCDfrHnvltk3csO4s4rNA=; b=X0le3669kWGIDoXvB8G84rUHtshs0pJoGn4mmAYHxaksuOmTpaBH1Ybo/2nt4nKVCt j+OaoFTR/rnClE2NgBHRwPtZU5pPcXw/9QjxZP0DVPzVGERa+rNIe3WIHL+BHrjDG0wE iqoXYi+qbTB3zAK54tOU8kccafjVKhHX1WHlyhfRBQHE6sGWAQoeZKQntygU41ogdOoQ OiS3ywJIFPCcE7GsPoMxT+KyiBBO6JrBoRm4EkK+RmqVQ2vxW92Ueu8T805/AUKBHB1+ X2ZT/R1p2o/CcnDQ4A00qBwy4vykh/tKMzIwyx4Kl0EOjtW2CwWmi216cT9luqdV6EGY 47jg== X-Gm-Message-State: APjAAAWSjVXTJHUVr0qdskQZj/DZHheAH9mBQLofonKp5jlzC15EKgEB dN1WG0UohgZME9QNMGcMZpeOJ+1pMWggx80P X-Received: by 2002:a17:902:322:: with SMTP id 31mr8866304pld.244.1574932666011; Thu, 28 Nov 2019 01:17:46 -0800 (PST) Received: from nsathish-Latitude-7480.iind.intel.com (jfdmzpr05-ext.jf.intel.com. [134.134.139.74]) by smtp.gmail.com with ESMTPSA id a12sm18733577pga.11.2019.11.28.01.17.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Nov 2019 01:17:45 -0800 (PST) From: Sathish Narsimman X-Google-Original-From: Sathish Narsimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman , Chethan T N , Hsin-Yu Chao , Amit K Bag Subject: [PATCH v4 2/2] bluetooth:btusb: handle msbc audio over USB Endpoints Date: Thu, 28 Nov 2019 14:47:48 +0530 Message-Id: <20191128091748.24531-2-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191128091748.24531-1-sathish.narasimman@intel.com> References: <20191128091748.24531-1-sathish.narasimman@intel.com> Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Sathish Narasimman For msbc encoded audio stream over usb transport, btusb driver to be set to alternate settings 6 as per BT core spec 5.0. The type of air mode is used to differenting which alt setting to be used. The changes are made considering some discussion over the similar patch submitted earlier from Kuba Pawlak(link below) https://www.spinics.net/lists/linux-bluetooth/msg64577.html Reported-by: kbuild test robot Signed-off-by: Sathish Narasimman Signed-off-by: Chethan T N Signed-off-by: Hsin-Yu Chao Signed-off-by: Amit K Bag --- drivers/bluetooth/btusb.c | 160 +++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 37 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 82fb2e7b2892..dc2af70a3b8d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -483,6 +483,8 @@ struct btusb_data { __u8 cmdreq; unsigned int sco_num; + unsigned int air_mode; + bool usb_alt6_packet_flow; int isoc_altsetting; int suspend_count; @@ -974,6 +976,42 @@ static void btusb_isoc_complete(struct urb *urb) } } +static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len, + int mtu, bool packet_flow) +{ + int i, offset = 0; + unsigned int interval; + + /* For msbc ALT 6 setting the host will send the packet at continuous + * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting + * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets. + * To maintain the rate we send 63bytes of usb packets alternatively for + * 7ms and 8ms to maintain the rate as 7.5ms. + */ + if (packet_flow) { + interval = 7; + packet_flow = false; + } else { + interval = 6; + packet_flow = true; + } + + BT_DBG("interval:%d len %d mtu %d", interval, len, mtu); + + for (i = 0; i < interval; i++) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = offset; + } + + if (len && i < BTUSB_MAX_ISOC_FRAMES) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = len; + i++; + } + + urb->number_of_packets = i; +} + static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu) { int i, offset = 0; @@ -1377,9 +1415,13 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb) urb->transfer_flags = URB_ISO_ASAP; - __fill_isoc_descriptor(urb, skb->len, + if (data->isoc_altsetting == 6) + __fill_isoc_descriptor_msbc(urb, skb->len, + le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize), + data->usb_alt6_packet_flow); + else + __fill_isoc_descriptor(urb, skb->len, le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); - skb->dev = (void *)hdev; return urb; @@ -1473,8 +1515,10 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt) BT_DBG("%s evt %d", hdev->name, evt); - if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) { + if ((evt != HCI_NOTIFY_CONN_ADD) + && (hci_conn_num(hdev, SCO_LINK) != data->sco_num)) { data->sco_num = hci_conn_num(hdev, SCO_LINK); + data->air_mode = evt; schedule_work(&data->work); } } @@ -1522,11 +1566,70 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting) return 0; } +static int bt_switch_alt_setting(struct hci_dev *hdev, int new_alts) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + int err; + + if (data->isoc_altsetting != new_alts) { + unsigned long flags; + + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->isoc_anchor); + + /* When isochronous alternate setting needs to be + * changed, because SCO connection has been added + * or removed, a packet fragment may be left in the + * reassembling state. This could lead to wrongly + * assembled fragments. + * + * Clear outstanding fragment when selecting a new + * alternate setting. + */ + spin_lock_irqsave(&data->rxlock, flags); + kfree_skb(data->sco_skb); + data->sco_skb = NULL; + spin_unlock_irqrestore(&data->rxlock, flags); + + err = __set_isoc_interface(hdev, new_alts); + if (err < 0) + return err; + } + if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { + if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0) + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + else + btusb_submit_isoc_urb(hdev, GFP_KERNEL); + } + + return 0; +} + +static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data, int alt) +{ + struct usb_interface *intf = data->isoc; + int i; + + BT_DBG("Looking for Alt no :%d", alt); + + if (intf == NULL) { + BT_ERR("INterface NULL"); + return NULL; + } + + for (i = 0; i < intf->num_altsetting; i++) { + if (intf->altsetting[i].desc.bAlternateSetting == alt) + return &intf->altsetting[i]; + } + + return NULL; +} + static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; - int new_alts; + int new_alts = 0; int err; if (data->sco_num > 0) { @@ -1541,44 +1644,27 @@ static void btusb_work(struct work_struct *work) set_bit(BTUSB_DID_ISO_RESUME, &data->flags); } - if (hdev->voice_setting & 0x0020) { - static const int alts[3] = { 2, 4, 5 }; - - new_alts = alts[data->sco_num - 1]; - } else { - new_alts = data->sco_num; - } - - if (data->isoc_altsetting != new_alts) { - unsigned long flags; + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->isoc_anchor); - - /* When isochronous alternate setting needs to be - * changed, because SCO connection has been added - * or removed, a packet fragment may be left in the - * reassembling state. This could lead to wrongly - * assembled fragments. - * - * Clear outstanding fragment when selecting a new - * alternate setting. - */ - spin_lock_irqsave(&data->rxlock, flags); - kfree_skb(data->sco_skb); - data->sco_skb = NULL; - spin_unlock_irqrestore(&data->rxlock, flags); + new_alts = alts[data->sco_num - 1]; + } else { + new_alts = data->sco_num; + } + } else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) { - if (__set_isoc_interface(hdev, new_alts) < 0) - return; - } + data->usb_alt6_packet_flow = true; - if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { - if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0) - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + /* Check if Alt 6 is supported for Transparent audio*/ + if (btusb_find_altsetting(data, 6)) + new_alts = 6; else - btusb_submit_isoc_urb(hdev, GFP_KERNEL); + BT_ERR("%s Device does not support ALT setting 6", hdev->name); } + + if (bt_switch_alt_setting(hdev, new_alts) < 0) + BT_ERR("%s Set USB Alt: %d failed!", hdev->name, new_alts); } else { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->isoc_anchor); -- 2.17.1