@@ -492,6 +492,8 @@ struct btusb_data {
492
492
__u8 cmdreq ;
493
493
494
494
unsigned int sco_num ;
495
+ unsigned int air_mode ;
496
+ bool usb_alt6_packet_flow ;
495
497
int isoc_altsetting ;
496
498
int suspend_count ;
497
499
@@ -983,6 +985,42 @@ static void btusb_isoc_complete(struct urb *urb)
983
985
}
984
986
}
985
987
988
+ static inline void __fill_isoc_descriptor_msbc (struct urb * urb , int len ,
989
+ int mtu , struct btusb_data * data )
990
+ {
991
+ int i , offset = 0 ;
992
+ unsigned int interval ;
993
+
994
+ BT_DBG ("len %d mtu %d" , len , mtu );
995
+
996
+ /* For mSBC ALT 6 setting the host will send the packet at continuous
997
+ * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
998
+ * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
999
+ * To maintain the rate we send 63bytes of usb packets alternatively for
1000
+ * 7ms and 8ms to maintain the rate as 7.5ms.
1001
+ */
1002
+ if (data -> usb_alt6_packet_flow ) {
1003
+ interval = 7 ;
1004
+ data -> usb_alt6_packet_flow = false;
1005
+ } else {
1006
+ interval = 6 ;
1007
+ data -> usb_alt6_packet_flow = true;
1008
+ }
1009
+
1010
+ for (i = 0 ; i < interval ; i ++ ) {
1011
+ urb -> iso_frame_desc [i ].offset = offset ;
1012
+ urb -> iso_frame_desc [i ].length = offset ;
1013
+ }
1014
+
1015
+ if (len && i < BTUSB_MAX_ISOC_FRAMES ) {
1016
+ urb -> iso_frame_desc [i ].offset = offset ;
1017
+ urb -> iso_frame_desc [i ].length = len ;
1018
+ i ++ ;
1019
+ }
1020
+
1021
+ urb -> number_of_packets = i ;
1022
+ }
1023
+
986
1024
static inline void __fill_isoc_descriptor (struct urb * urb , int len , int mtu )
987
1025
{
988
1026
int i , offset = 0 ;
@@ -1386,9 +1424,13 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
1386
1424
1387
1425
urb -> transfer_flags = URB_ISO_ASAP ;
1388
1426
1389
- __fill_isoc_descriptor (urb , skb -> len ,
1390
- le16_to_cpu (data -> isoc_tx_ep -> wMaxPacketSize ));
1391
-
1427
+ if (data -> isoc_altsetting == 6 )
1428
+ __fill_isoc_descriptor_msbc (urb , skb -> len ,
1429
+ le16_to_cpu (data -> isoc_tx_ep -> wMaxPacketSize ),
1430
+ data );
1431
+ else
1432
+ __fill_isoc_descriptor (urb , skb -> len ,
1433
+ le16_to_cpu (data -> isoc_tx_ep -> wMaxPacketSize ));
1392
1434
skb -> dev = (void * )hdev ;
1393
1435
1394
1436
return urb ;
@@ -1484,6 +1526,7 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
1484
1526
1485
1527
if (hci_conn_num (hdev , SCO_LINK ) != data -> sco_num ) {
1486
1528
data -> sco_num = hci_conn_num (hdev , SCO_LINK );
1529
+ data -> air_mode = evt ;
1487
1530
schedule_work (& data -> work );
1488
1531
}
1489
1532
}
@@ -1531,11 +1574,67 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
1531
1574
return 0 ;
1532
1575
}
1533
1576
1577
+ static int btusb_switch_alt_setting (struct hci_dev * hdev , int new_alts )
1578
+ {
1579
+ struct btusb_data * data = hci_get_drvdata (hdev );
1580
+ int err ;
1581
+
1582
+ if (data -> isoc_altsetting != new_alts ) {
1583
+ unsigned long flags ;
1584
+
1585
+ clear_bit (BTUSB_ISOC_RUNNING , & data -> flags );
1586
+ usb_kill_anchored_urbs (& data -> isoc_anchor );
1587
+
1588
+ /* When isochronous alternate setting needs to be
1589
+ * changed, because SCO connection has been added
1590
+ * or removed, a packet fragment may be left in the
1591
+ * reassembling state. This could lead to wrongly
1592
+ * assembled fragments.
1593
+ *
1594
+ * Clear outstanding fragment when selecting a new
1595
+ * alternate setting.
1596
+ */
1597
+ spin_lock_irqsave (& data -> rxlock , flags );
1598
+ kfree_skb (data -> sco_skb );
1599
+ data -> sco_skb = NULL ;
1600
+ spin_unlock_irqrestore (& data -> rxlock , flags );
1601
+
1602
+ err = __set_isoc_interface (hdev , new_alts );
1603
+ if (err < 0 )
1604
+ return err ;
1605
+ }
1606
+
1607
+ if (!test_and_set_bit (BTUSB_ISOC_RUNNING , & data -> flags )) {
1608
+ if (btusb_submit_isoc_urb (hdev , GFP_KERNEL ) < 0 )
1609
+ clear_bit (BTUSB_ISOC_RUNNING , & data -> flags );
1610
+ else
1611
+ btusb_submit_isoc_urb (hdev , GFP_KERNEL );
1612
+ }
1613
+
1614
+ return 0 ;
1615
+ }
1616
+
1617
+ static struct usb_host_interface * btusb_find_altsetting (struct btusb_data * data ,
1618
+ int alt )
1619
+ {
1620
+ struct usb_interface * intf = data -> isoc ;
1621
+ int i ;
1622
+
1623
+ BT_DBG ("Looking for Alt no :%d" , alt );
1624
+
1625
+ for (i = 0 ; i < intf -> num_altsetting ; i ++ ) {
1626
+ if (intf -> altsetting [i ].desc .bAlternateSetting == alt )
1627
+ return & intf -> altsetting [i ];
1628
+ }
1629
+
1630
+ return NULL ;
1631
+ }
1632
+
1534
1633
static void btusb_work (struct work_struct * work )
1535
1634
{
1536
1635
struct btusb_data * data = container_of (work , struct btusb_data , work );
1537
1636
struct hci_dev * hdev = data -> hdev ;
1538
- int new_alts ;
1637
+ int new_alts = 0 ;
1539
1638
int err ;
1540
1639
1541
1640
if (data -> sco_num > 0 ) {
@@ -1550,44 +1649,27 @@ static void btusb_work(struct work_struct *work)
1550
1649
set_bit (BTUSB_DID_ISO_RESUME , & data -> flags );
1551
1650
}
1552
1651
1553
- if (hdev -> voice_setting & 0x0020 ) {
1554
- static const int alts [3 ] = { 2 , 4 , 5 };
1555
-
1556
- new_alts = alts [data -> sco_num - 1 ];
1557
- } else {
1558
- new_alts = data -> sco_num ;
1559
- }
1560
-
1561
- if (data -> isoc_altsetting != new_alts ) {
1562
- unsigned long flags ;
1652
+ if (data -> air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD ) {
1653
+ if (hdev -> voice_setting & 0x0020 ) {
1654
+ static const int alts [3 ] = { 2 , 4 , 5 };
1563
1655
1564
- clear_bit (BTUSB_ISOC_RUNNING , & data -> flags );
1565
- usb_kill_anchored_urbs (& data -> isoc_anchor );
1566
-
1567
- /* When isochronous alternate setting needs to be
1568
- * changed, because SCO connection has been added
1569
- * or removed, a packet fragment may be left in the
1570
- * reassembling state. This could lead to wrongly
1571
- * assembled fragments.
1572
- *
1573
- * Clear outstanding fragment when selecting a new
1574
- * alternate setting.
1575
- */
1576
- spin_lock_irqsave (& data -> rxlock , flags );
1577
- kfree_skb (data -> sco_skb );
1578
- data -> sco_skb = NULL ;
1579
- spin_unlock_irqrestore (& data -> rxlock , flags );
1656
+ new_alts = alts [data -> sco_num - 1 ];
1657
+ } else {
1658
+ new_alts = data -> sco_num ;
1659
+ }
1660
+ } else if (data -> air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP ) {
1580
1661
1581
- if (__set_isoc_interface (hdev , new_alts ) < 0 )
1582
- return ;
1583
- }
1662
+ data -> usb_alt6_packet_flow = true;
1584
1663
1585
- if (! test_and_set_bit ( BTUSB_ISOC_RUNNING , & data -> flags )) {
1586
- if (btusb_submit_isoc_urb ( hdev , GFP_KERNEL ) < 0 )
1587
- clear_bit ( BTUSB_ISOC_RUNNING , & data -> flags ) ;
1664
+ /* Check if Alt 6 is supported for Transparent audio */
1665
+ if (btusb_find_altsetting ( data , 6 ) )
1666
+ new_alts = 6 ;
1588
1667
else
1589
- btusb_submit_isoc_urb (hdev , GFP_KERNEL );
1668
+ bt_dev_err (hdev , "Device does not support ALT setting 6" );
1590
1669
}
1670
+
1671
+ if (btusb_switch_alt_setting (hdev , new_alts ) < 0 )
1672
+ bt_dev_err (hdev , "set USB alt:(%d) failed!" , new_alts );
1591
1673
} else {
1592
1674
clear_bit (BTUSB_ISOC_RUNNING , & data -> flags );
1593
1675
usb_kill_anchored_urbs (& data -> isoc_anchor );
0 commit comments