18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * USB Debug cable driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Greg Kroah-Hartman <greg@kroah.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/gfp.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/tty.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/usb.h> 138c2ecf20Sopenharmony_ci#include <linux/usb/serial.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define USB_DEBUG_MAX_PACKET_SIZE 8 168c2ecf20Sopenharmony_ci#define USB_DEBUG_BRK_SIZE 8 178c2ecf20Sopenharmony_cistatic const char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = { 188c2ecf20Sopenharmony_ci 0x00, 198c2ecf20Sopenharmony_ci 0xff, 208c2ecf20Sopenharmony_ci 0x01, 218c2ecf20Sopenharmony_ci 0xfe, 228c2ecf20Sopenharmony_ci 0x00, 238c2ecf20Sopenharmony_ci 0xfe, 248c2ecf20Sopenharmony_ci 0x01, 258c2ecf20Sopenharmony_ci 0xff, 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic const struct usb_device_id id_table[] = { 298c2ecf20Sopenharmony_ci { USB_DEVICE(0x0525, 0x127a) }, 308c2ecf20Sopenharmony_ci { }, 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic const struct usb_device_id dbc_id_table[] = { 348c2ecf20Sopenharmony_ci { USB_DEVICE(0x1d6b, 0x0010) }, 358c2ecf20Sopenharmony_ci { USB_DEVICE(0x1d6b, 0x0011) }, 368c2ecf20Sopenharmony_ci { }, 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic const struct usb_device_id id_table_combined[] = { 408c2ecf20Sopenharmony_ci { USB_DEVICE(0x0525, 0x127a) }, 418c2ecf20Sopenharmony_ci { USB_DEVICE(0x1d6b, 0x0010) }, 428c2ecf20Sopenharmony_ci { USB_DEVICE(0x1d6b, 0x0011) }, 438c2ecf20Sopenharmony_ci { }, 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, id_table_combined); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* This HW really does not support a serial break, so one will be 488c2ecf20Sopenharmony_ci * emulated when ever the break state is set to true. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cistatic void usb_debug_break_ctl(struct tty_struct *tty, int break_state) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci struct usb_serial_port *port = tty->driver_data; 538c2ecf20Sopenharmony_ci if (!break_state) 548c2ecf20Sopenharmony_ci return; 558c2ecf20Sopenharmony_ci usb_serial_generic_write(tty, port, USB_DEBUG_BRK, USB_DEBUG_BRK_SIZE); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic void usb_debug_process_read_urb(struct urb *urb) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct usb_serial_port *port = urb->context; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (urb->actual_length == USB_DEBUG_BRK_SIZE && 638c2ecf20Sopenharmony_ci memcmp(urb->transfer_buffer, USB_DEBUG_BRK, 648c2ecf20Sopenharmony_ci USB_DEBUG_BRK_SIZE) == 0) { 658c2ecf20Sopenharmony_ci usb_serial_handle_break(port); 668c2ecf20Sopenharmony_ci return; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci usb_serial_generic_process_read_urb(urb); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic struct usb_serial_driver debug_device = { 738c2ecf20Sopenharmony_ci .driver = { 748c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 758c2ecf20Sopenharmony_ci .name = "debug", 768c2ecf20Sopenharmony_ci }, 778c2ecf20Sopenharmony_ci .id_table = id_table, 788c2ecf20Sopenharmony_ci .num_ports = 1, 798c2ecf20Sopenharmony_ci .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, 808c2ecf20Sopenharmony_ci .break_ctl = usb_debug_break_ctl, 818c2ecf20Sopenharmony_ci .process_read_urb = usb_debug_process_read_urb, 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic struct usb_serial_driver dbc_device = { 858c2ecf20Sopenharmony_ci .driver = { 868c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 878c2ecf20Sopenharmony_ci .name = "xhci_dbc", 888c2ecf20Sopenharmony_ci }, 898c2ecf20Sopenharmony_ci .id_table = dbc_id_table, 908c2ecf20Sopenharmony_ci .num_ports = 1, 918c2ecf20Sopenharmony_ci .break_ctl = usb_debug_break_ctl, 928c2ecf20Sopenharmony_ci .process_read_urb = usb_debug_process_read_urb, 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic struct usb_serial_driver * const serial_drivers[] = { 968c2ecf20Sopenharmony_ci &debug_device, &dbc_device, NULL 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cimodule_usb_serial_driver(serial_drivers, id_table_combined); 1008c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 101