@@ -278,6 +278,100 @@ static int vhci_setup(struct hci_dev *hdev)
278278 return 0 ;
279279}
280280
281+ static void vhci_coredump (struct hci_dev * hdev )
282+ {
283+ /* No need to do anything */
284+ }
285+
286+ static void vhci_coredump_hdr (struct hci_dev * hdev , struct sk_buff * skb )
287+ {
288+ char buf [80 ];
289+
290+ snprintf (buf , sizeof (buf ), "Controller Name: vhci_ctrl\n" );
291+ skb_put_data (skb , buf , strlen (buf ));
292+
293+ snprintf (buf , sizeof (buf ), "Firmware Version: vhci_fw\n" );
294+ skb_put_data (skb , buf , strlen (buf ));
295+
296+ snprintf (buf , sizeof (buf ), "Driver: vhci_drv\n" );
297+ skb_put_data (skb , buf , strlen (buf ));
298+
299+ snprintf (buf , sizeof (buf ), "Vendor: vhci\n" );
300+ skb_put_data (skb , buf , strlen (buf ));
301+ }
302+
303+ #define MAX_COREDUMP_LINE_LEN 40
304+
305+ struct devcoredump_test_data {
306+ enum devcoredump_state state ;
307+ unsigned int timeout ;
308+ char data [MAX_COREDUMP_LINE_LEN ];
309+ };
310+
311+ static inline void force_devcd_timeout (struct hci_dev * hdev ,
312+ unsigned int timeout )
313+ {
314+ #ifdef CONFIG_DEV_COREDUMP
315+ hdev -> dump .timeout = msecs_to_jiffies (timeout * 1000 );
316+ #endif
317+ }
318+
319+ static ssize_t force_devcd_write (struct file * file , const char __user * user_buf ,
320+ size_t count , loff_t * ppos )
321+ {
322+ struct vhci_data * data = file -> private_data ;
323+ struct hci_dev * hdev = data -> hdev ;
324+ struct sk_buff * skb = NULL ;
325+ struct devcoredump_test_data dump_data ;
326+ int ret ;
327+
328+ ret = simple_write_to_buffer (& dump_data , sizeof (dump_data ), ppos ,
329+ user_buf , count );
330+ if (ret < count )
331+ return ret ;
332+
333+ skb = alloc_skb (sizeof (dump_data .data ), GFP_ATOMIC );
334+ if (!skb )
335+ return - ENOMEM ;
336+ skb_put_data (skb , & dump_data .data , sizeof (dump_data .data ));
337+
338+ hci_devcd_register (hdev , vhci_coredump , vhci_coredump_hdr , NULL );
339+
340+ /* Force the devcoredump timeout */
341+ if (dump_data .timeout )
342+ force_devcd_timeout (hdev , dump_data .timeout );
343+
344+ ret = hci_devcd_init (hdev , skb -> len );
345+ if (ret ) {
346+ BT_ERR ("Failed to generate devcoredump" );
347+ kfree_skb (skb );
348+ return ret ;
349+ }
350+
351+ hci_devcd_append (hdev , skb );
352+
353+ switch (dump_data .state ) {
354+ case HCI_DEVCOREDUMP_DONE :
355+ hci_devcd_complete (hdev );
356+ break ;
357+ case HCI_DEVCOREDUMP_ABORT :
358+ hci_devcd_abort (hdev );
359+ break ;
360+ case HCI_DEVCOREDUMP_TIMEOUT :
361+ /* Do nothing */
362+ break ;
363+ default :
364+ return - EINVAL ;
365+ }
366+
367+ return count ;
368+ }
369+
370+ static const struct file_operations force_devcoredump_fops = {
371+ .open = simple_open ,
372+ .write = force_devcd_write ,
373+ };
374+
281375static int __vhci_create_device (struct vhci_data * data , __u8 opcode )
282376{
283377 struct hci_dev * hdev ;
@@ -355,6 +449,9 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
355449 debugfs_create_file ("aosp_capable" , 0644 , hdev -> debugfs , data ,
356450 & aosp_capable_fops );
357451
452+ debugfs_create_file ("force_devcoredump" , 0644 , hdev -> debugfs , data ,
453+ & force_devcoredump_fops );
454+
358455 hci_skb_pkt_type (skb ) = HCI_VENDOR_PKT ;
359456
360457 skb_put_u8 (skb , 0xff );
0 commit comments