@@ -44,6 +44,11 @@ struct sco_param {
4444 u8 retrans_effort ;
4545};
4646
47+ struct conn_handle_t {
48+ struct hci_conn * conn ;
49+ __u16 handle ;
50+ };
51+
4752static const struct sco_param esco_param_cvsd [] = {
4853 { EDR_ESCO_MASK & ~ESCO_2EV3 , 0x000a , 0x01 }, /* S3 */
4954 { EDR_ESCO_MASK & ~ESCO_2EV3 , 0x0007 , 0x01 }, /* S2 */
@@ -316,17 +321,60 @@ static bool find_next_esco_param(struct hci_conn *conn,
316321 return conn -> attempt <= size ;
317322}
318323
319- static bool hci_enhanced_setup_sync_conn (struct hci_conn * conn , __u16 handle )
324+ static int configure_datapath_sync (struct hci_dev * hdev , struct bt_codec * codec )
320325{
321- struct hci_dev * hdev = conn -> hdev ;
326+ int err ;
327+ __u8 vnd_len , * vnd_data = NULL ;
328+ struct hci_op_configure_data_path * cmd = NULL ;
329+
330+ err = hdev -> get_codec_config_data (hdev , ESCO_LINK , codec , & vnd_len ,
331+ & vnd_data );
332+ if (err < 0 )
333+ goto error ;
334+
335+ cmd = kzalloc (sizeof (* cmd ) + vnd_len , GFP_KERNEL );
336+ if (!cmd ) {
337+ err = - ENOMEM ;
338+ goto error ;
339+ }
340+
341+ err = hdev -> get_data_path_id (hdev , & cmd -> data_path_id );
342+ if (err < 0 )
343+ goto error ;
344+
345+ cmd -> vnd_len = vnd_len ;
346+ memcpy (cmd -> vnd_data , vnd_data , vnd_len );
347+
348+ cmd -> direction = 0x00 ;
349+ __hci_cmd_sync_status (hdev , HCI_CONFIGURE_DATA_PATH ,
350+ sizeof (* cmd ) + vnd_len , cmd , HCI_CMD_TIMEOUT );
351+
352+ cmd -> direction = 0x01 ;
353+ err = __hci_cmd_sync_status (hdev , HCI_CONFIGURE_DATA_PATH ,
354+ sizeof (* cmd ) + vnd_len , cmd ,
355+ HCI_CMD_TIMEOUT );
356+ error :
357+
358+ kfree (cmd );
359+ kfree (vnd_data );
360+ return err ;
361+ }
362+
363+ static int hci_enhanced_setup_sync (struct hci_dev * hdev , void * data )
364+ {
365+ struct conn_handle_t * conn_handle = data ;
366+ struct hci_conn * conn = conn_handle -> conn ;
367+ __u16 handle = conn_handle -> handle ;
322368 struct hci_cp_enhanced_setup_sync_conn cp ;
323369 const struct sco_param * param ;
324370
371+ kfree (conn_handle );
372+
325373 bt_dev_dbg (hdev , "hcon %p" , conn );
326374
327375 /* for offload use case, codec needs to configured before opening SCO */
328376 if (conn -> codec .data_path )
329- hci_req_configure_datapath (hdev , & conn -> codec );
377+ configure_datapath_sync (hdev , & conn -> codec );
330378
331379 conn -> state = BT_CONNECT ;
332380 conn -> out = true;
@@ -344,7 +392,7 @@ static bool hci_enhanced_setup_sync_conn(struct hci_conn *conn, __u16 handle)
344392 case BT_CODEC_MSBC :
345393 if (!find_next_esco_param (conn , esco_param_msbc ,
346394 ARRAY_SIZE (esco_param_msbc )))
347- return false ;
395+ return - EINVAL ;
348396
349397 param = & esco_param_msbc [conn -> attempt - 1 ];
350398 cp .tx_coding_format .id = 0x05 ;
@@ -396,11 +444,11 @@ static bool hci_enhanced_setup_sync_conn(struct hci_conn *conn, __u16 handle)
396444 if (lmp_esco_capable (conn -> link )) {
397445 if (!find_next_esco_param (conn , esco_param_cvsd ,
398446 ARRAY_SIZE (esco_param_cvsd )))
399- return false ;
447+ return - EINVAL ;
400448 param = & esco_param_cvsd [conn -> attempt - 1 ];
401449 } else {
402450 if (conn -> attempt > ARRAY_SIZE (sco_param_cvsd ))
403- return false ;
451+ return - EINVAL ;
404452 param = & sco_param_cvsd [conn -> attempt - 1 ];
405453 }
406454 cp .tx_coding_format .id = 2 ;
@@ -423,17 +471,17 @@ static bool hci_enhanced_setup_sync_conn(struct hci_conn *conn, __u16 handle)
423471 cp .out_transport_unit_size = 16 ;
424472 break ;
425473 default :
426- return false ;
474+ return - EINVAL ;
427475 }
428476
429477 cp .retrans_effort = param -> retrans_effort ;
430478 cp .pkt_type = __cpu_to_le16 (param -> pkt_type );
431479 cp .max_latency = __cpu_to_le16 (param -> max_latency );
432480
433481 if (hci_send_cmd (hdev , HCI_OP_ENHANCED_SETUP_SYNC_CONN , sizeof (cp ), & cp ) < 0 )
434- return false ;
482+ return - EIO ;
435483
436- return true ;
484+ return 0 ;
437485}
438486
439487static bool hci_setup_sync_conn (struct hci_conn * conn , __u16 handle )
@@ -490,8 +538,24 @@ static bool hci_setup_sync_conn(struct hci_conn *conn, __u16 handle)
490538
491539bool hci_setup_sync (struct hci_conn * conn , __u16 handle )
492540{
493- if (enhanced_sync_conn_capable (conn -> hdev ))
494- return hci_enhanced_setup_sync_conn (conn , handle );
541+ int result ;
542+ struct conn_handle_t * conn_handle ;
543+
544+ if (enhanced_sync_conn_capable (conn -> hdev )) {
545+ conn_handle = kzalloc (sizeof (* conn_handle ), GFP_KERNEL );
546+
547+ if (!conn_handle )
548+ return false;
549+
550+ conn_handle -> conn = conn ;
551+ conn_handle -> handle = handle ;
552+ result = hci_cmd_sync_queue (conn -> hdev , hci_enhanced_setup_sync ,
553+ conn_handle , NULL );
554+ if (result < 0 )
555+ kfree (conn_handle );
556+
557+ return result == 0 ;
558+ }
495559
496560 return hci_setup_sync_conn (conn , handle );
497561}
0 commit comments