⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gmidi.c

📁 linux下面gadget设备驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		case 0xf1:		case 0xf3:			port->data[0] = b;			port->state = STATE_1PARAM;			break;		case 0xf2:			port->data[0] = b;			port->state = STATE_2PARAM_1;			break;		case 0xf4:		case 0xf5:			port->state = STATE_UNKNOWN;			break;		case 0xf6:			gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0);			port->state = STATE_UNKNOWN;			break;		case 0xf7:			switch (port->state) {			case STATE_SYSEX_0:				gmidi_transmit_packet(req,					p0 | 0x05, 0xf7, 0, 0);				break;			case STATE_SYSEX_1:				gmidi_transmit_packet(req,					p0 | 0x06, port->data[0], 0xf7, 0);				break;			case STATE_SYSEX_2:				gmidi_transmit_packet(req,					p0 | 0x07, port->data[0],					port->data[1], 0xf7);				break;			}			port->state = STATE_UNKNOWN;			break;		}	} else if (b >= 0x80) {		port->data[0] = b;		if (b >= 0xc0 && b <= 0xdf)			port->state = STATE_1PARAM;		else			port->state = STATE_2PARAM_1;	} else { /* b < 0x80 */		switch (port->state) {		case STATE_1PARAM:			if (port->data[0] < 0xf0) {				p0 |= port->data[0] >> 4;			} else {				p0 |= 0x02;				port->state = STATE_UNKNOWN;			}			gmidi_transmit_packet(req, p0, port->data[0], b, 0);			break;		case STATE_2PARAM_1:			port->data[1] = b;			port->state = STATE_2PARAM_2;			break;		case STATE_2PARAM_2:			if (port->data[0] < 0xf0) {				p0 |= port->data[0] >> 4;				port->state = STATE_2PARAM_1;			} else {				p0 |= 0x03;				port->state = STATE_UNKNOWN;			}			gmidi_transmit_packet(req,				p0, port->data[0], port->data[1], b);			break;		case STATE_SYSEX_0:			port->data[0] = b;			port->state = STATE_SYSEX_1;			break;		case STATE_SYSEX_1:			port->data[1] = b;			port->state = STATE_SYSEX_2;			break;		case STATE_SYSEX_2:			gmidi_transmit_packet(req,				p0 | 0x04, port->data[0], port->data[1], b);			port->state = STATE_SYSEX_0;			break;		}	}}static void gmidi_transmit(struct gmidi_device *dev, struct usb_request *req){	struct usb_ep *ep = dev->in_ep;	struct gmidi_in_port *port = &dev->in_port;	if (!ep) {		return;	}	if (!req) {		req = alloc_ep_req(ep, buflen);	}	if (!req) {		ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n");		return;	}	req->length = 0;	req->complete = gmidi_complete;	if (port->active) {		while (req->length + 3 < buflen) {			uint8_t b;			if (snd_rawmidi_transmit(dev->in_substream, &b, 1)				!= 1)			{				port->active = 0;				break;			}			gmidi_transmit_byte(req, port, b);		}	}	if (req->length > 0) {		usb_ep_queue(ep, req, GFP_ATOMIC);	} else {		free_ep_req(ep, req);	}}static void gmidi_in_tasklet(unsigned long data){	struct gmidi_device *dev = (struct gmidi_device *)data;	gmidi_transmit(dev, NULL);}static int gmidi_in_open(struct snd_rawmidi_substream *substream){	struct gmidi_device *dev = substream->rmidi->private_data;	VDBG(dev, "gmidi_in_open\n");	dev->in_substream = substream;	dev->in_port.state = STATE_UNKNOWN;	return 0;}static int gmidi_in_close(struct snd_rawmidi_substream *substream){	struct gmidi_device *dev = substream->rmidi->private_data;	VDBG(dev, "gmidi_in_close\n");	return 0;}static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up){	struct gmidi_device *dev = substream->rmidi->private_data;	VDBG(dev, "gmidi_in_trigger %d\n", up);	dev->in_port.active = up;	if (up) {		tasklet_hi_schedule(&dev->tasklet);	}}static int gmidi_out_open(struct snd_rawmidi_substream *substream){	struct gmidi_device *dev = substream->rmidi->private_data;	VDBG(dev, "gmidi_out_open\n");	dev->out_substream = substream;	return 0;}static int gmidi_out_close(struct snd_rawmidi_substream *substream){	struct gmidi_device *dev = substream->rmidi->private_data;	VDBG(dev, "gmidi_out_close\n");	return 0;}static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up){	struct gmidi_device *dev = substream->rmidi->private_data;	VDBG(dev, "gmidi_out_trigger %d\n", up);	if (up) {		set_bit(substream->number, &dev->out_triggered);	} else {		clear_bit(substream->number, &dev->out_triggered);	}}static struct snd_rawmidi_ops gmidi_in_ops = {	.open = gmidi_in_open,	.close = gmidi_in_close,	.trigger = gmidi_in_trigger,};static struct snd_rawmidi_ops gmidi_out_ops = {	.open = gmidi_out_open,	.close = gmidi_out_close,	.trigger = gmidi_out_trigger};/* register as a sound "card" */static int gmidi_register_card(struct gmidi_device *dev){	struct snd_card *card;	struct snd_rawmidi *rmidi;	int err;	int out_ports = 1;	int in_ports = 1;	static struct snd_device_ops ops = {		.dev_free = gmidi_snd_free,	};	card = snd_card_new(index, id, THIS_MODULE, 0);	if (!card) {		ERROR(dev, "snd_card_new failed\n");		err = -ENOMEM;		goto fail;	}	dev->card = card;	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops);	if (err < 0) {		ERROR(dev, "snd_device_new failed: error %d\n", err);		goto fail;	}	strcpy(card->driver, longname);	strcpy(card->longname, longname);	strcpy(card->shortname, shortname);	/* Set up rawmidi */	dev->in_port.dev = dev;	dev->in_port.active = 0;	snd_component_add(card, "MIDI");	err = snd_rawmidi_new(card, "USB MIDI Gadget", 0,			      out_ports, in_ports, &rmidi);	if (err < 0) {		ERROR(dev, "snd_rawmidi_new failed: error %d\n", err);		goto fail;	}	dev->rmidi = rmidi;	strcpy(rmidi->name, card->shortname);	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |			    SNDRV_RAWMIDI_INFO_INPUT |			    SNDRV_RAWMIDI_INFO_DUPLEX;	rmidi->private_data = dev;	/* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.	   It's an upside-down world being a gadget. */	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops);	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops);	snd_card_set_dev(card, &dev->gadget->dev);	/* register it - we're ready to go */	err = snd_card_register(card);	if (err < 0) {		ERROR(dev, "snd_card_register failed\n");		goto fail;	}	VDBG(dev, "gmidi_register_card finished ok\n");	return 0;fail:	if (dev->card) {		snd_card_free(dev->card);		dev->card = NULL;	}	return err;}/* * Creates an output endpoint, and initializes output ports. */static int __devinit gmidi_bind(struct usb_gadget *gadget){	struct gmidi_device *dev;	struct usb_ep *in_ep, *out_ep;	int gcnum, err = 0;	/* support optional vendor/distro customization */	if (idVendor) {		if (!idProduct) {			printk(KERN_ERR "idVendor needs idProduct!\n");			return -ENODEV;		}		device_desc.idVendor = cpu_to_le16(idVendor);		device_desc.idProduct = cpu_to_le16(idProduct);		if (bcdDevice) {			device_desc.bcdDevice = cpu_to_le16(bcdDevice);		}	}	if (iManufacturer) {		strlcpy(manufacturer, iManufacturer, sizeof(manufacturer));	} else {		snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",			init_utsname()->sysname, init_utsname()->release,			gadget->name);	}	if (iProduct) {		strlcpy(product_desc, iProduct, sizeof(product_desc));	}	if (iSerialNumber) {		device_desc.iSerialNumber = STRING_SERIAL,		strlcpy(serial_number, iSerialNumber, sizeof(serial_number));	}	/* Bulk-only drivers like this one SHOULD be able to	 * autoconfigure on any sane usb controller driver,	 * but there may also be important quirks to address.	 */	usb_ep_autoconfig_reset(gadget);	in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);	if (!in_ep) {autoconf_fail:		printk(KERN_ERR "%s: can't autoconfigure on %s\n",			shortname, gadget->name);		return -ENODEV;	}	EP_IN_NAME = in_ep->name;	in_ep->driver_data = in_ep;	/* claim */	out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc);	if (!out_ep) {		goto autoconf_fail;	}	EP_OUT_NAME = out_ep->name;	out_ep->driver_data = out_ep;	/* claim */	gcnum = usb_gadget_controller_number(gadget);	if (gcnum >= 0) {		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);	} else {		/* gmidi is so simple (no altsettings) that		 * it SHOULD NOT have problems with bulk-capable hardware.		 * so warn about unrecognized controllers, don't panic.		 */		printk(KERN_WARNING "%s: controller '%s' not recognized\n",			shortname, gadget->name);		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);	}	/* ok, we made sense of the hardware ... */	dev = kzalloc(sizeof(*dev), GFP_KERNEL);	if (!dev) {		return -ENOMEM;	}	spin_lock_init(&dev->lock);	dev->gadget = gadget;	dev->in_ep = in_ep;	dev->out_ep = out_ep;	set_gadget_data(gadget, dev);	tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);	/* preallocate control response and buffer */	dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ);	if (!dev->req) {		err = -ENOMEM;		goto fail;	}	dev->req->complete = gmidi_setup_complete;	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;	gadget->ep0->driver_data = dev;	INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,		EP_OUT_NAME, EP_IN_NAME);	/* register as an ALSA sound card */	err = gmidi_register_card(dev);	if (err < 0) {		goto fail;	}	VDBG(dev, "gmidi_bind finished ok\n");	return 0;fail:	gmidi_unbind(gadget);	return err;}static void gmidi_suspend(struct usb_gadget *gadget){	struct gmidi_device *dev = get_gadget_data(gadget);	if (gadget->speed == USB_SPEED_UNKNOWN) {		return;	}	DBG(dev, "suspend\n");}static void gmidi_resume(struct usb_gadget *gadget){	struct gmidi_device *dev = get_gadget_data(gadget);	DBG(dev, "resume\n");}static struct usb_gadget_driver gmidi_driver = {	.speed		= USB_SPEED_FULL,	.function	= (char *)longname,	.bind		= gmidi_bind,	.unbind		= gmidi_unbind,	.setup		= gmidi_setup,	.disconnect	= gmidi_disconnect,	.suspend	= gmidi_suspend,	.resume		= gmidi_resume,	.driver		= {		.name		= (char *)shortname,		.owner		= THIS_MODULE,	},};static int __init gmidi_init(void){	return usb_gadget_register_driver(&gmidi_driver);}module_init(gmidi_init);static void __exit gmidi_cleanup(void){	usb_gadget_unregister_driver(&gmidi_driver);}module_exit(gmidi_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -