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

📄 usb-midi.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		printk(KERN_ERR "usbmidi: no memory for midi out-endpoint buffer\n");		kfree(ep);		return NULL;	}	ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */	if ( !ep->urb ) {		printk(KERN_ERR "usbmidi: no memory for midi out-endpoint urb\n");		kfree(ep->buf);		kfree(ep);		return NULL;	}	ep->bufSize       = bufSize;	/* ep->bufWrPtr      = 0; */	init_waitqueue_head(&ep->wait);	return ep;}static int remove_midi_out_endpoint( struct midi_out_endpoint *mout ){	usb_unlink_urb( mout->urb );	usb_free_urb( mout->urb );	kfree( mout->buf );	kfree( mout );	return 0;}/** Returns a filled usb_mididev structure, registered as a Linux MIDI device. * * Returns null if memory is not available or the device cannot be registered. * Called by allocUsbMidiDev(); * **/static struct usb_mididev *allocMidiDev(	struct usb_midi_state *s,	struct midi_in_endpoint *min,	struct midi_out_endpoint *mout,	int inCableId,	int outCableId ){	struct usb_mididev *m;	m = (struct usb_mididev *)kmalloc(sizeof(struct usb_mididev), GFP_KERNEL);	if (!m) {		printk(KERN_ERR "usbmidi: no memory for midi device\n");		return NULL;	}	memset(m, 0, sizeof(struct usb_mididev));	if ((m->dev_midi = register_sound_midi(&usb_midi_fops, -1)) < 0) {		printk(KERN_ERR "usbmidi: cannot register midi device\n");		kfree(m);		return NULL;	}	m->midi               = s;	/* m->open_mode          = 0; */	if ( min ) {		m->min.ep             = min;		m->min.ep->usbdev     = s->usbdev;		m->min.cableId        = inCableId;	}	/* m->min.bufPtr         = 0; */	/* m->min.bufRemains     = 0; */	if ( mout ) {		m->mout.ep            = mout;		m->mout.ep->usbdev    = s->usbdev;		m->mout.cableId       = outCableId;	}	/* m->mout.bufPtr        = 0; */	/* m->mout.bufRemains    = 0; */	/* m->mout.isInExclusive = 0; */	/* m->mout.lastEvent     = 0; */	m->singlebyte         = singlebyte;	return m;}static void release_midi_device( struct usb_midi_state *s ){	struct usb_mididev *m;	struct midi_in_endpoint *min;	struct midi_out_endpoint *mout;	if ( s->count > 0 ) {		up(&open_sem);		return;	}	up( &open_sem );	wake_up( &open_wait );	while(!list_empty(&s->inEndpointList)) {		min = list_entry(s->inEndpointList.next, struct midi_in_endpoint, list);		list_del(&min->list);		remove_midi_in_endpoint(min);	}	while(!list_empty(&s->outEndpointList)) {		mout = list_entry(s->outEndpointList.next, struct midi_out_endpoint, list);		list_del(&mout->list);		remove_midi_out_endpoint(mout);	}	while(!list_empty(&s->midiDevList)) {		m = list_entry(s->midiDevList.next, struct usb_mididev, list);		list_del(&m->list);		kfree(m);	}	kfree(s);	return;}/* ------------------------------------------------------------------------- *//** Utility routine to find a descriptor in a dump of many descriptors. * Returns start of descriptor or NULL if not found.  * descStart pointer to list of interfaces. * descLength length (in bytes) of dump * after (ignored if NULL) this routine returns only descriptors after "after" * dtype (mandatory) The descriptor type. * iface (ignored if -1) returns descriptor at/following given interface * altSetting (ignored if -1) returns descriptor at/following given altSetting * * *  Called by parseDescriptor(), find_csinterface_descriptor(); * */static void *find_descriptor( void *descStart, unsigned int descLength, void *after, unsigned char dtype, int iface, int altSetting ){	unsigned char *p, *end, *next;	int interfaceNumber = -1, altSet = -1;	p = descStart;	end = p + descLength;	for( ; p < end; ) {		if ( p[0] < 2 )			return NULL;		next = p + p[0];		if ( next > end )			return NULL;		if ( p[1] == USB_DT_INTERFACE ) {			if ( p[0] < USB_DT_INTERFACE_SIZE )				return NULL;			interfaceNumber = p[2];			altSet = p[3];		}		if ( p[1] == dtype &&		     ( !after || ( p > (unsigned char *)after) ) &&		     ( ( iface == -1) || (iface == interfaceNumber) ) &&		     ( (altSetting == -1) || (altSetting == altSet) )) {			return p;		}		p = next;	}	return NULL;}/** Utility to find a class-specific interface descriptor. *  dsubtype is a descriptor subtype *  Called by parseDescriptor(); **/static void *find_csinterface_descriptor(void *descStart, unsigned int descLength, void *after, u8 dsubtype, int iface, int altSetting){	unsigned char *p;  	p = find_descriptor( descStart, descLength, after, USB_DT_CS_INTERFACE, iface, altSetting );	while ( p ) {		if ( p[0] >= 3 && p[2] == dsubtype )			return p;		p = find_descriptor( descStart, descLength, p, USB_DT_CS_INTERFACE, 				     iface, altSetting );	}	return NULL;}/** The magic of making a new usb_midi_device from config happens here. * * The caller is responsible for free-ing this return value (if not NULL). * **/static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned char *buffer, int bufSize, unsigned int ifnum , unsigned int altSetting, int quirks){	struct usb_midi_device *u;	unsigned char *p1;	unsigned char *p2;	unsigned char *next;	int iep, oep;	int length;	unsigned long longBits;	int pins, nbytes, offset, shift, jack;#ifdef HAVE_JACK_STRINGS	/** Jacks can have associated names.  **/	unsigned char jack2string[256];#endif	u = NULL;	/* find audiocontrol interface */	p1 = find_csinterface_descriptor( buffer, bufSize, NULL,					  MS_HEADER, ifnum, altSetting);	if ( !p1 ) {		goto error_end;	}	if ( p1[0] < MS_HEADER_LENGTH ) {		goto error_end;	}	/* Assume success. Since the device corresponds to USB-MIDI spec, we assume	   that the rest of the USB 2.0 spec is obeyed. */	u = (struct usb_midi_device *)kmalloc( sizeof(struct usb_midi_device), GFP_KERNEL );	if ( !u ) {		return NULL;	}	u->deviceName = NULL;	u->idVendor = d->descriptor.idVendor;	u->idProduct = d->descriptor.idProduct;	u->interface = ifnum;	u->altSetting = altSetting;	u->in[0].endpoint = -1;	u->in[0].cableId = -1;	u->out[0].endpoint = -1;	u->out[0].cableId = -1;	printk(KERN_INFO "usb-midi: Found MIDIStreaming device corresponding to Release %d.%02d of spec.\n",	       (p1[4] >> 4) * 10 + (p1[4] & 0x0f ),	       (p1[3] >> 4) * 10 + (p1[3] & 0x0f )		);	length = p1[5] | (p1[6] << 8);#ifdef HAVE_JACK_STRINGS	memset(jack2string, 0, sizeof(unsigned char) * 256);#endif	length -= p1[0];	for (p2 = p1 + p1[0]; length > 0; p2 = next) {		next = p2 + p2[0];		length -= p2[0];		if (p2[0] < 2 )			break;		if (p2[1] != USB_DT_CS_INTERFACE)			break;		if (p2[2] == MIDI_IN_JACK && p2[0] >= 6 ) {			jack = p2[4];#ifdef HAVE_JACK_STRINGS			jack2string[jack] = p2[5];#endif			printk(KERN_INFO "usb-midi: Found IN Jack 0x%02x %s\n",			       jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL" );		} else if ( p2[2] == MIDI_OUT_JACK && p2[0] >= 6) {			pins = p2[5];			if ( p2[0] < (6 + 2 * pins) )				continue;			jack = p2[4];#ifdef HAVE_JACK_STRINGS			jack2string[jack] = p2[5 + 2 * pins];#endif			printk(KERN_INFO "usb-midi: Found OUT Jack 0x%02x %s, %d pins\n",			       jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL", pins );		} else if ( p2[2] == ELEMENT_DESCRIPTOR  && p2[0]  >= 10) {			pins = p2[4];			if ( p2[0] < (9 + 2 * pins ) )				continue;			nbytes = p2[8 + 2 * pins ];			if ( p2[0] < (10 + 2 * pins + nbytes) )				continue;			longBits = 0L;			for ( offset = 0, shift = 0; offset < nbytes && offset < 8; offset ++, shift += 8) {				longBits |= ((long)(p2[9 + 2 * pins + offset])) << shift;			}			jack = p2[3];#ifdef HAVE_JACK_STRINGS			jack2string[jack] = p2[9 + 2 * pins + nbytes];#endif			printk(KERN_INFO "usb-midi: Found ELEMENT 0x%02x, %d/%d pins in/out, bits: 0x%016lx\n",			       jack, pins, (int)(p2[5 + 2 * pins]), (long)longBits );		} else {		}	}	iep=0;	oep=0;	if (quirks==0) {		/* MIDISTREAM */		p2 = NULL;		for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT,					  ifnum, altSetting ); p1; p1 = next ) {			next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT,					       ifnum, altSetting ); 			p2 = find_descriptor(buffer, bufSize, p1, USB_DT_CS_ENDPOINT,					     ifnum, altSetting ); 			if ( p2 && next && ( p2 > next ) )				p2 = NULL;			if ( p1[0] < 9 || !p2 || p2[0] < 4 )				continue;			if ( (p1[2] & 0x80) == 0x80 ) {				if ( iep < 15 ) {					pins = p2[3]; /* not pins -- actually "cables" */					if ( pins > 16 )						pins = 16;					u->in[iep].endpoint = p1[2];					u->in[iep].cableId = ( 1 << pins ) - 1;					if ( u->in[iep].cableId )						iep ++;					if ( iep < 15 ) {						u->in[iep].endpoint = -1;						u->in[iep].cableId = -1;					}				}			} else {				if ( oep < 15 ) {					pins = p2[3]; /* not pins -- actually "cables" */					if ( pins > 16 )						pins = 16;					u->out[oep].endpoint = p1[2];					u->out[oep].cableId = ( 1 << pins ) - 1;					if ( u->out[oep].cableId )						oep ++;					if ( oep < 15 ) {						u->out[oep].endpoint = -1;						u->out[oep].cableId = -1;					}				}			}			}	} else if (quirks==1) {		/* YAMAHA quirks */		for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT,					  ifnum, altSetting ); p1; p1 = next ) {			next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT,					       ifnum, altSetting ); 				if ( p1[0] < 7 )				continue;			if ( (p1[2] & 0x80) == 0x80 ) {				if ( iep < 15 ) {					pins = iep+1;					if ( pins > 16 )						pins = 16;					u->in[iep].endpoint = p1[2];					u->in[iep].cableId = ( 1 << pins ) - 1;					if ( u->in[iep].cableId )						iep ++;					if ( iep < 15 ) {						u->in[iep].endpoint = -1;						u->in[iep].cableId = -1;					}				}			} else {				if ( oep < 15 ) {					pins = oep+1;					if ( pins > 16 )						pins = 16;					u->out[oep].endpoint = p1[2];					u->out[oep].cableId = ( 1 << pins ) - 1;					if ( u->out[oep].cableId )						oep ++;					if ( oep < 15 ) {						u->out[oep].endpoint = -1;						u->out[oep].cableId = -1;					}				}			}			}	}	if ( !iep && ! oep ) {		goto error_end;	}	return u;error_end:	kfree(u);	return NULL;}/* ------------------------------------------------------------------------- *//** Returns number between 0 and 16. * **/static int on_bits( unsigned short v ){	int i;	int ret=0;	for ( i=0 ; i<16 ; i++ ) {		if ( v & (1<<i) )			ret++;	}	return ret;}/** USB-device will be interrogated for altSetting. * * Returns negative on error. * Called by allocUsbMidiDev(); * **/static int get_alt_setting( struct usb_device *d, int ifnum ){	int alts, alt=0;	struct usb_interface *iface;	struct usb_host_interface *interface;	struct usb_endpoint_descriptor *ep;	int epin, epout;	int i;	iface = usb_ifnum_to_if( d, ifnum );	alts = iface->num_altsetting;	for ( alt=0 ; alt<alts ; alt++ ) {		interface = &iface->altsetting[alt];		epin = -1;		epout = -1;		for ( i=0 ; i<interface->desc.bNumEndpoints ; i++ ) {			ep = &interface->endpoint[i].desc;			if ( (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ) {				continue;			}			if ( (ep->bEndpointAddress & USB_DIR_IN) && epin < 0 ) {				epin = i;			} else if ( epout < 0 ) {				epout = i;			}			if ( epin >= 0 && epout >= 0 ) {				return interface->desc.bAlternateSetting;			}		}	}	return -ENODEV;}/* ------------------------------------------------------------------------- *//** Returns 0 if successful in allocating and registering internal structures. * Returns negative on failure. * Calls allocMidiDev which additionally registers /dev/midiXX devices. * Writes messages on success to indicate which /dev/midiXX is which physical * endpoint. * **/static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s, struct usb_midi_device *u ){	struct usb_mididev **mdevs=NULL;	struct midi_in_endpoint *mins[15], *min;	struct midi_out_endpoint *mouts[15], *mout;	int inDevs=0, outDevs=0;	int inEndpoints=0, outEndpoints=0;	int inEndpoint, outEndpoint;	int inCableId, outCableId;	int i;	int devices = 0;	int alt = 0;	/* Obtain altSetting or die.. */	alt = u->altSetting;	if ( alt < 0 ) {		alt = get_alt_setting( d, u->interface );	}	if ( alt < 0 )		return -ENXIO;	/* Configure interface */	if ( usb_set_interface( d, u->interface, alt ) < 0 ) {		return -ENXIO;	}	for ( i = 0 ; i < 15 ; i++ ) {		mins[i] = NULL;		mouts[i] = NULL;	}	/* Begin Allocation */	while( inEndpoints < 15	       && inDevs < maxdevices	       && u->in[inEndpoints].cableId >= 0 ) {		inDevs += on_bits((unsigned short)u->in[inEndpoints].cableId);		mins[inEndpoints] = alloc_midi_in_endpoint( d, u->in[inEndpoints].endpoint );		if ( mins[inEndpoints] == NULL )			goto error_end;		inEndpoints++;	}	while( outEndpoints < 15	       && outDevs < maxdevices	       && u->out[outEndpoints].cableId >= 0 ) {		outDevs += on_bits((unsigned short)u->out[outEndpoints].cableId);		mouts[outEndpoints] = alloc_midi_out_endpoint( d, u->out[outEndpoints].endpoint );		if ( mouts[outEndpoints] == NULL )			goto error_end;		outEndpoints++;	}	devices = inDevs > outDevs ? inDevs : outDevs;	devices = maxdevices > devices ? devices : maxdevices;	/* obtain space for device name (iProduct) if not known. */	if ( ! u->deviceName ) {		mdevs = (struct usb_mididev **)			kmalloc(sizeof(struct usb_mididevs *)*devices				+ sizeof(char) * 256, GFP_KERNEL);	} else {		mdevs = (struct usb_mididev **)			kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL);	}

⌨️ 快捷键说明

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