On Tue, Apr 20, 2010 at 05:45:44PM +0200, sdaau wrote: > Hi all, > > I am trying to learn more about interfacing with FT232, and I started with > ftdi_sio.c as a base, and my final goal is being able to interface with > snd_pcm and ALSA (and I'm trying to use usbaudio functions as examples). A usb serial audio device? Huh? That doesn't sound correct at all. > For that purpose, I am trying to build a module, where a modification of > ftdi_sio.c is one object, and another .c file with corresponding ALSA > functions is another object built into this module. Needless to say, I'm > quite struggling to keep all the structs involved in mind :) What exacly are you trying to do here that you would need to modify both of these drivers? > For now, I just want to come to the point where probe and disconnect work. > I have tried to add additional commands to ftdi_sio_probe and > ftdi_shutdown, so functions (my_extra_probe and my_extra_disconnect) in the > other .c file get called. > > Probe seems to work fine (i.e. a new card can be seen in cat /dev/sndstat), > however, it is the disconnect I have a problem with. The problem is that in > ftdi_sio_probe, after my_extra_probe, what corresponds to > usb_serial->interface->dev->driver_data is a valid pointer -- however, > whenever ftdi_shutdown is called, this ...->driver_data is always a null > pointer (even if ftdi_open was never called). Unfortunately, the functions > from usbaudio are using precisely this "property" to proceed with > deregistering. Below is a snippet from these two functions: > > --- > /* Probe function to check for special devices */ > static int ftdi_sio_probe(struct usb_serial *serial, > const struct usb_device_id *id) > { > struct snd_ftdi_audard_quirk *quirk = > (struct snd_ftdi_audard_quirk *)id->driver_info; > > struct usb_interface *interface = serial->interface; // added > int ret; > ... > usb_set_serial_data(serial, (void *)id->driver_info); > > ret = my_extra_probe(interface, id); > dbg("%s: RET is %d ... (&interface->dev)->driver_data %p", __func__, ret, > (&interface->dev)->driver_data); > /* > * Here (&interface->dev)->driver_data is an OK pointer, > * same as the one traced from within my_extra_probe, > * where it is set. > */ > return 0; > } > > static void ftdi_shutdown(struct usb_serial *serial) > { > struct usb_interface *interface = serial->interface; // added > > dbg("%s - (&interface->dev)->driver_data %p", __func__, > (&interface->dev)->driver_data); > /* > * Here (&interface->dev)->driver_data is NULL pointer, > * which is a problem, because my_extra_disconnect needs it > */ > > my_extra_disconnect(interface); > } > --- > > So these are the questions I have: > > - Is there an easy/obvious reason, why this pointer is reset at _shutdown, > that I'm missing? I'm missing the connection between these two drivers. The problem is you can't have 2 drivers binding to the same usb interface, which is what you are doing here. Bad things happen as you have seen :) > - How could I debug this? Ideally, I'd like to put a watch on > usb_serial->interface->dev->driver_data and see when it changes (and what > changes it) - but its not even a variable :) Yes it is, it's a variable otherwise you would not be able to reference it :) > I have just learned that I could recompile a kernel and use something > called kgdb, which needs two machines; I found > http://linux-hacks.blogspot.com/2008/05/setting-up-kgdb-using-kvmqemu.html > that uses a VM instead - but I'm afraid using a VM will mess up everything > USB related. Any links to some resources related to this kind of debugging? You could just use kdb if you like assembly language. good luck, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html