18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * USB Empeg empeg-car player driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *	Copyright (C) 2000, 2001
68c2ecf20Sopenharmony_ci *	    Gary Brubaker (xavyer@ix.netcom.com)
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *	Copyright (C) 1999 - 2001
98c2ecf20Sopenharmony_ci *	    Greg Kroah-Hartman (greg@kroah.com)
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * See Documentation/usb/usb-serial.rst for more information on using this
128c2ecf20Sopenharmony_ci * driver
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/errno.h>
178c2ecf20Sopenharmony_ci#include <linux/slab.h>
188c2ecf20Sopenharmony_ci#include <linux/tty.h>
198c2ecf20Sopenharmony_ci#include <linux/tty_driver.h>
208c2ecf20Sopenharmony_ci#include <linux/tty_flip.h>
218c2ecf20Sopenharmony_ci#include <linux/module.h>
228c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
238c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
248c2ecf20Sopenharmony_ci#include <linux/usb.h>
258c2ecf20Sopenharmony_ci#include <linux/usb/serial.h>
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"
288c2ecf20Sopenharmony_ci#define DRIVER_DESC "USB Empeg Mark I/II Driver"
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define EMPEG_VENDOR_ID			0x084f
318c2ecf20Sopenharmony_ci#define EMPEG_PRODUCT_ID		0x0001
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* function prototypes for an empeg-car player */
348c2ecf20Sopenharmony_cistatic int  empeg_startup(struct usb_serial *serial);
358c2ecf20Sopenharmony_cistatic void empeg_init_termios(struct tty_struct *tty);
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic const struct usb_device_id id_table[] = {
388c2ecf20Sopenharmony_ci	{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
398c2ecf20Sopenharmony_ci	{ }					/* Terminating entry */
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, id_table);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic struct usb_serial_driver empeg_device = {
458c2ecf20Sopenharmony_ci	.driver = {
468c2ecf20Sopenharmony_ci		.owner =	THIS_MODULE,
478c2ecf20Sopenharmony_ci		.name =		"empeg",
488c2ecf20Sopenharmony_ci	},
498c2ecf20Sopenharmony_ci	.id_table =		id_table,
508c2ecf20Sopenharmony_ci	.num_ports =		1,
518c2ecf20Sopenharmony_ci	.bulk_out_size =	256,
528c2ecf20Sopenharmony_ci	.throttle =		usb_serial_generic_throttle,
538c2ecf20Sopenharmony_ci	.unthrottle =		usb_serial_generic_unthrottle,
548c2ecf20Sopenharmony_ci	.attach =		empeg_startup,
558c2ecf20Sopenharmony_ci	.init_termios =		empeg_init_termios,
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic struct usb_serial_driver * const serial_drivers[] = {
598c2ecf20Sopenharmony_ci	&empeg_device, NULL
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic int empeg_startup(struct usb_serial *serial)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	int r;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
678c2ecf20Sopenharmony_ci		dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
688c2ecf20Sopenharmony_ci			serial->dev->actconfig->desc.bConfigurationValue);
698c2ecf20Sopenharmony_ci		return -ENODEV;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	r = usb_reset_configuration(serial->dev);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* continue on with initialization */
758c2ecf20Sopenharmony_ci	return r;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic void empeg_init_termios(struct tty_struct *tty)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	struct ktermios *termios = &tty->termios;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	/*
838c2ecf20Sopenharmony_ci	 * The empeg-car player wants these particular tty settings.
848c2ecf20Sopenharmony_ci	 * You could, for example, change the baud rate, however the
858c2ecf20Sopenharmony_ci	 * player only supports 115200 (currently), so there is really
868c2ecf20Sopenharmony_ci	 * no point in support for changes to the tty settings.
878c2ecf20Sopenharmony_ci	 * (at least for now)
888c2ecf20Sopenharmony_ci	 *
898c2ecf20Sopenharmony_ci	 * The default requirements for this device are:
908c2ecf20Sopenharmony_ci	 */
918c2ecf20Sopenharmony_ci	termios->c_iflag
928c2ecf20Sopenharmony_ci		&= ~(IGNBRK	/* disable ignore break */
938c2ecf20Sopenharmony_ci		| BRKINT	/* disable break causes interrupt */
948c2ecf20Sopenharmony_ci		| PARMRK	/* disable mark parity errors */
958c2ecf20Sopenharmony_ci		| ISTRIP	/* disable clear high bit of input characters */
968c2ecf20Sopenharmony_ci		| INLCR		/* disable translate NL to CR */
978c2ecf20Sopenharmony_ci		| IGNCR		/* disable ignore CR */
988c2ecf20Sopenharmony_ci		| ICRNL		/* disable translate CR to NL */
998c2ecf20Sopenharmony_ci		| IXON);	/* disable enable XON/XOFF flow control */
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	termios->c_oflag
1028c2ecf20Sopenharmony_ci		&= ~OPOST;	/* disable postprocess output characters */
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	termios->c_lflag
1058c2ecf20Sopenharmony_ci		&= ~(ECHO	/* disable echo input characters */
1068c2ecf20Sopenharmony_ci		| ECHONL	/* disable echo new line */
1078c2ecf20Sopenharmony_ci		| ICANON	/* disable erase, kill, werase, and rprnt special characters */
1088c2ecf20Sopenharmony_ci		| ISIG		/* disable interrupt, quit, and suspend special characters */
1098c2ecf20Sopenharmony_ci		| IEXTEN);	/* disable non-POSIX special characters */
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	termios->c_cflag
1128c2ecf20Sopenharmony_ci		&= ~(CSIZE	/* no size */
1138c2ecf20Sopenharmony_ci		| PARENB	/* disable parity bit */
1148c2ecf20Sopenharmony_ci		| CBAUD);	/* clear current baud rate */
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	termios->c_cflag
1178c2ecf20Sopenharmony_ci		|= CS8;		/* character size 8 bits */
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	tty_encode_baud_rate(tty, 115200, 115200);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cimodule_usb_serial_driver(serial_drivers, id_table);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ciMODULE_AUTHOR(DRIVER_AUTHOR);
1258c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
1268c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
127