mirror of https://github.com/wb2osz/direwolf.git
				
				
				
			Recognize more ALSA audio "card" formats for matching to
corresponding HID devices for PTT.
This commit is contained in:
		
							parent
							
								
									316c8d8194
								
							
						
					
					
						commit
						357f2e633c
					
				
							
								
								
									
										171
									
								
								cm108.c
								
								
								
								
							
							
						
						
									
										171
									
								
								cm108.c
								
								
								
								
							| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//    This file is part of Dire Wolf, an amateur radio packet TNC.
 | 
					//    This file is part of Dire Wolf, an amateur radio packet TNC.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//    Copyright (C) 2017  John Langner, WB2OSZ
 | 
					//    Copyright (C) 2017,2019  John Langner, WB2OSZ
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//    Parts of this were adapted from "hamlib" which contains the notice:
 | 
					//    Parts of this were adapted from "hamlib" which contains the notice:
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
| 
						 | 
					@ -31,10 +31,11 @@
 | 
				
			||||||
 * Description:
 | 
					 * Description:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	There is an incresing demand for using the GPIO pins of USB audio devices for PTT.
 | 
					 *	There is an incresing demand for using the GPIO pins of USB audio devices for PTT.
 | 
				
			||||||
 *	We have a couple commercial products:
 | 
					 *	We have a few commercial products:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		DMK URI		http://www.dmkeng.com/URI_Order_Page.htm
 | 
					 *		DMK URI		http://www.dmkeng.com/URI_Order_Page.htm
 | 
				
			||||||
 *		RB-USB RIM	http://www.repeater-builder.com/products/usb-rim-lite.html
 | 
					 *		RB-USB RIM	http://www.repeater-builder.com/products/usb-rim-lite.html
 | 
				
			||||||
 | 
					 *		RA-35		http://www.masterscommunications.com/products/radio-adapter/ra35.html
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	and homebrew projects which are all very similar.
 | 
					 *	and homebrew projects which are all very similar.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -47,7 +48,7 @@
 | 
				
			||||||
 *	
 | 
					 *	
 | 
				
			||||||
 *	Soundmodem and hamlib paved the way but didn't get too far.
 | 
					 *	Soundmodem and hamlib paved the way but didn't get too far.
 | 
				
			||||||
 *	Dire Wolf 1.3 added HAMLIB support (Linux only) which theoretically allows this in a
 | 
					 *	Dire Wolf 1.3 added HAMLIB support (Linux only) which theoretically allows this in a
 | 
				
			||||||
 *	roundabout way.  This is documented in the User Guide, section called,
 | 
					 *	painful roundabout way.  This is documented in the User Guide, section called,
 | 
				
			||||||
 *		 "Hamlib PTT Example 2: Use GPIO of USB audio adapter.  (e.g. DMK URI)"
 | 
					 *		 "Hamlib PTT Example 2: Use GPIO of USB audio adapter.  (e.g. DMK URI)"
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	It's rather involved and the explantion doesn't cover the case of multiple
 | 
					 *	It's rather involved and the explantion doesn't cover the case of multiple
 | 
				
			||||||
| 
						 | 
					@ -215,7 +216,7 @@ static int cm108_write (char *name, int iomask, int iodata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Used to process regular expression matching results.
 | 
					// Used to process regular expression matching results.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void inline substr_se (char *dest, const char *src, int start, int endp1)
 | 
					static void substr_se (char *dest, const char *src, int start, int endp1)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int len = endp1 - start;
 | 
						int len = endp1 - start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -234,14 +235,19 @@ static void inline substr_se (char *dest, const char *src, int start, int endp1)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct thing_s {
 | 
					struct thing_s {
 | 
				
			||||||
	int vid;		// vendor id
 | 
						int vid;		// vendor id, displayed as four hexadecimal digits.
 | 
				
			||||||
	int pid;		// product id
 | 
						int pid;		// product id, displayed as four hexadecimal digits.
 | 
				
			||||||
 | 
						char card_number[8];	// Number.  e.g.  2 for plughw:2,0
 | 
				
			||||||
 | 
						char card_name[32];	// Name, assigned by system (e.g. Device_1) or by udev rule.
 | 
				
			||||||
	char product[32];	// product name (e.g. manufacturer, model)
 | 
						char product[32];	// product name (e.g. manufacturer, model)
 | 
				
			||||||
	char devnode_sound[22];	// e.g. /dev/snd/pcmC0D0p
 | 
						char devnode_sound[22];	// e.g. /dev/snd/pcmC0D0p
 | 
				
			||||||
	char plughw[72];	// Above in more familiar format e.g. plughw:0,0
 | 
						char plughw[72];	// Above in more familiar format e.g. plughw:0,0
 | 
				
			||||||
				// Oversized to silence a compiler warning.
 | 
									// Oversized to silence a compiler warning.
 | 
				
			||||||
 | 
						char plughw2[72];	// With name rather than number.
 | 
				
			||||||
 | 
						char devpath[128];	// Kernel dev path.  Does not include /sys mount point.
 | 
				
			||||||
	char devnode_hidraw[17]; // e.g. /dev/hidraw3
 | 
						char devnode_hidraw[17]; // e.g. /dev/hidraw3
 | 
				
			||||||
	char devnode_usb[25];	// e.g. /dev/bus/usb/001/012
 | 
						char devnode_usb[25];	// e.g. /dev/bus/usb/001/012
 | 
				
			||||||
 | 
									// This is what we use to match up audio and HID.
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cm108_inventory (struct thing_s *things, int max_things);
 | 
					int cm108_inventory (struct thing_s *things, int max_things);
 | 
				
			||||||
| 
						 | 
					@ -251,13 +257,12 @@ int cm108_inventory (struct thing_s *things, int max_things);
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Name:	main
 | 
					 * Name:	main
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Purpose:	Test program to list USB audio and HID devices.
 | 
					 * Purpose:	Useful utility to list USB audio and HID devices.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *		sudo apt-get install libudev-dev
 | 
					 | 
				
			||||||
 *		gcc -DCM108_MAIN textcolor.c -l udev
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *------------------------------------------------------------------*/
 | 
					 *------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#define EXTRA 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAXX_THINGS 60
 | 
					#define MAXX_THINGS 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CM108_MAIN
 | 
					#ifdef CM108_MAIN
 | 
				
			||||||
| 
						 | 
					@ -270,28 +275,32 @@ int main (void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	text_color_init (0);    // Turn off text color.
 | 
						text_color_init (0);    // Turn off text color.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Take inventory of USB Audio adapters and other HID devices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	num_things = cm108_inventory (things, MAXX_THINGS);
 | 
						num_things = cm108_inventory (things, MAXX_THINGS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dw_printf ("    VID  PID   %-*s %-*s %-*s %-*s"
 | 
						dw_printf ("    VID  PID   %-*s %-*s %-*s %-*s %-*s"
 | 
				
			||||||
#if EXTRA
 | 
					#if EXTRA
 | 
				
			||||||
						" %-*s"
 | 
											" %-*s"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
						"\n", 	(int)sizeof(things[0].product),	"Product",
 | 
											"\n", 	(int)sizeof(things[0].product),	"Product",
 | 
				
			||||||
							(int)sizeof(things[0].devnode_sound), "Sound",
 | 
												(int)sizeof(things[0].devnode_sound), "Sound",
 | 
				
			||||||
							(int)sizeof(things[0].plughw), "ADEVICE",
 | 
												(int)sizeof(things[0].plughw)/5, "ADEVICE",
 | 
				
			||||||
 | 
												(int)sizeof(things[0].plughw2)/4, "ADEVICE",
 | 
				
			||||||
							(int)sizeof(things[0].devnode_hidraw), "HID [ptt]"
 | 
												(int)sizeof(things[0].devnode_hidraw), "HID [ptt]"
 | 
				
			||||||
#if EXTRA
 | 
					#if EXTRA
 | 
				
			||||||
							, (int)sizeof(things[0].devnode_usb), "USB"
 | 
												, (int)sizeof(things[0].devnode_usb), "USB"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
							);
 | 
												);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dw_printf ("    ---  ---   %-*s %-*s %-*s %-*s"
 | 
						dw_printf ("    ---  ---   %-*s %-*s %-*s %-*s %-*s"
 | 
				
			||||||
#if EXTRA
 | 
					#if EXTRA
 | 
				
			||||||
						" %-*s"
 | 
											" %-*s"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
						"\n", 	(int)sizeof(things[0].product),	"-------",
 | 
											"\n", 	(int)sizeof(things[0].product),	"-------",
 | 
				
			||||||
							(int)sizeof(things[0].devnode_sound), "-----",
 | 
												(int)sizeof(things[0].devnode_sound), "-----",
 | 
				
			||||||
							(int)sizeof(things[0].plughw), "-------",
 | 
												(int)sizeof(things[0].plughw)/5, "-------",
 | 
				
			||||||
 | 
												(int)sizeof(things[0].plughw2)/4, "-------",
 | 
				
			||||||
							(int)sizeof(things[0].devnode_hidraw), "---------"
 | 
												(int)sizeof(things[0].devnode_hidraw), "---------"
 | 
				
			||||||
#if EXTRA
 | 
					#if EXTRA
 | 
				
			||||||
							, (int)sizeof(things[0].devnode_usb), "---"
 | 
												, (int)sizeof(things[0].devnode_usb), "---"
 | 
				
			||||||
| 
						 | 
					@ -299,7 +308,7 @@ int main (void)
 | 
				
			||||||
							);
 | 
												);
 | 
				
			||||||
	for (i = 0; i < num_things; i++) {
 | 
						for (i = 0; i < num_things; i++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  dw_printf ("%2s  %04x %04x  %-*s %-*s %-*s %-*s"
 | 
						  dw_printf ("%2s  %04x %04x  %-*s %-*s %-*s %-*s %-*s"
 | 
				
			||||||
#if EXTRA
 | 
					#if EXTRA
 | 
				
			||||||
						" %-*s"
 | 
											" %-*s"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -308,14 +317,62 @@ int main (void)
 | 
				
			||||||
							things[i].vid, things[i].pid,
 | 
												things[i].vid, things[i].pid,
 | 
				
			||||||
							(int)sizeof(things[i].product),	things[i].product,
 | 
												(int)sizeof(things[i].product),	things[i].product,
 | 
				
			||||||
							(int)sizeof(things[i].devnode_sound), things[i].devnode_sound,
 | 
												(int)sizeof(things[i].devnode_sound), things[i].devnode_sound,
 | 
				
			||||||
							(int)sizeof(things[0].plughw), things[i].plughw,
 | 
												(int)sizeof(things[0].plughw)/5, things[i].plughw,
 | 
				
			||||||
 | 
												(int)sizeof(things[0].plughw2)/4, things[i].plughw2,
 | 
				
			||||||
							(int)sizeof(things[i].devnode_hidraw), things[i].devnode_hidraw
 | 
												(int)sizeof(things[i].devnode_hidraw), things[i].devnode_hidraw
 | 
				
			||||||
#if EXTRA
 | 
					#if EXTRA
 | 
				
			||||||
							, (int)sizeof(things[i].devnode_usb), things[i].devnode_usb
 | 
												, (int)sizeof(things[i].devnode_usb), things[i].devnode_usb
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
							);
 | 
												);
 | 
				
			||||||
 | 
						  //dw_printf ("             %-*s\n", (int)sizeof(things[i].devpath), things[i].devpath);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static const char *suggested_names[] = {"Fred", "Wilma", "Pebbles", "Dino", "Barney", "Betty", "Bamm_Bamm" };
 | 
				
			||||||
 | 
						int iname = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// From example in https://alsa.opensrc.org/Udev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dw_printf ("\n");
 | 
				
			||||||
 | 
						dw_printf ("** = Can use Audio Adapter GPIO for PTT.\n");
 | 
				
			||||||
 | 
						dw_printf ("\n");
 | 
				
			||||||
 | 
						dw_printf ("Notice that each USB Audio adapter is assigned a number and a name.  These are not predictable so you could\n");
 | 
				
			||||||
 | 
						dw_printf ("end up using the wrong adapter after adding or removing other USB devices or after rebooting.  You can assign a\n");
 | 
				
			||||||
 | 
						dw_printf ("name to each USB adapter so you can refer to the same one each time.  This can be based on any characteristics\n");
 | 
				
			||||||
 | 
						dw_printf ("that makes them unique such as product id or serial number.  Unfortunately these devices don't have unique serial\n");
 | 
				
			||||||
 | 
						dw_printf ("numbers so how can we tell them apart?  A name can also be assigned based on the physical USB socket.\n");
 | 
				
			||||||
 | 
						dw_printf ("Create a file like \"/etc/udev/rules.d/85-my-usb-audio.rules\" with the following contents and then reboot.\n");
 | 
				
			||||||
 | 
						dw_printf ("\n");
 | 
				
			||||||
 | 
						dw_printf ("SUBSYSTEM!=\"sound\", GOTO=\"my_usb_audio_end\"\n");
 | 
				
			||||||
 | 
						dw_printf ("ACTION!=\"add\", GOTO=\"my_usb_audio_end\"\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Consider only the 'devnode' paths that end with "card" and a number.
 | 
				
			||||||
 | 
					// Replace the number with a question mark.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						regex_t devpath_re;
 | 
				
			||||||
 | 
						char emsg[100];
 | 
				
			||||||
 | 
						// Drop any "/sys" at the beginning.
 | 
				
			||||||
 | 
						int e = regcomp (&devpath_re, "(/devices/.+/card)[0-9]$", REG_EXTENDED);
 | 
				
			||||||
 | 
						if (e) {
 | 
				
			||||||
 | 
						  regerror (e, &devpath_re, emsg, sizeof(emsg));
 | 
				
			||||||
 | 
						  text_color_set(DW_COLOR_ERROR);
 | 
				
			||||||
 | 
						  dw_printf("INTERNAL ERROR:  %s:%d: %s\n", __FILE__, __LINE__, emsg);
 | 
				
			||||||
 | 
						  return (-1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < num_things; i++) {
 | 
				
			||||||
 | 
						  if (i == 0 || strcmp(things[i].devpath,things[i-1].devpath) != 0) {
 | 
				
			||||||
 | 
						    regmatch_t devpath_match[2];
 | 
				
			||||||
 | 
						    if (regexec (&devpath_re, things[i].devpath, 2, devpath_match, 0) == 0) {
 | 
				
			||||||
 | 
						      char without_number[256];
 | 
				
			||||||
 | 
						      substr_se (without_number, things[i].devpath, devpath_match[1].rm_so, devpath_match[1].rm_eo);
 | 
				
			||||||
 | 
						      dw_printf ("DEVPATH==\"%s?\", ATTR{id}=\"%s\"\n", without_number, suggested_names[iname]);
 | 
				
			||||||
 | 
						      if (iname < 6) iname++;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dw_printf ("LABEL=\"my_usb_audio_end\"\n");
 | 
				
			||||||
 | 
						dw_printf ("\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,6 +406,10 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
	struct udev_device *dev;
 | 
						struct udev_device *dev;
 | 
				
			||||||
	struct udev_device *parentdev;
 | 
						struct udev_device *parentdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char const *pattrs_id = NULL;
 | 
				
			||||||
 | 
						char const *pattrs_number = NULL;
 | 
				
			||||||
 | 
						char card_devpath[128] = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int num_things = 0;
 | 
						int num_things = 0;
 | 
				
			||||||
	memset (things, 0, sizeof(struct thing_s) * max_things);
 | 
						memset (things, 0, sizeof(struct thing_s) * max_things);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -368,11 +429,21 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
	udev_enumerate_scan_devices(enumerate);
 | 
						udev_enumerate_scan_devices(enumerate);
 | 
				
			||||||
	devices = udev_enumerate_get_list_entry(enumerate);
 | 
						devices = udev_enumerate_get_list_entry(enumerate);
 | 
				
			||||||
	udev_list_entry_foreach(dev_list_entry, devices) {
 | 
						udev_list_entry_foreach(dev_list_entry, devices) {
 | 
				
			||||||
	  const char *path;
 | 
						  const char *path = udev_list_entry_get_name(dev_list_entry);
 | 
				
			||||||
	  path = udev_list_entry_get_name(dev_list_entry);
 | 
					 | 
				
			||||||
	  dev = udev_device_new_from_syspath(udev, path);
 | 
						  dev = udev_device_new_from_syspath(udev, path);
 | 
				
			||||||
	  char const *devnode = udev_device_get_devnode(dev);
 | 
						  char const *devnode = udev_device_get_devnode(dev);
 | 
				
			||||||
	  if (devnode != NULL) {
 | 
					
 | 
				
			||||||
 | 
						  if (devnode == NULL ) {
 | 
				
			||||||
 | 
						    // I'm not happy with this but couldn't figure out how
 | 
				
			||||||
 | 
						    // to get attributes from one level up from the pcmC?D?? node.
 | 
				
			||||||
 | 
						    strlcpy (card_devpath, path, sizeof(card_devpath));
 | 
				
			||||||
 | 
						    pattrs_id = udev_device_get_sysattr_value(dev,"id");
 | 
				
			||||||
 | 
						    pattrs_number = udev_device_get_sysattr_value(dev,"number");
 | 
				
			||||||
 | 
						    //dw_printf (" >card_devpath = %s\n", card_devpath);
 | 
				
			||||||
 | 
						    //dw_printf (" >>pattrs_id = %s\n", pattrs_id);
 | 
				
			||||||
 | 
						    //dw_printf (" >>pattrs_number = %s\n", pattrs_number);
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
						  else {
 | 
				
			||||||
	    parentdev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); 
 | 
						    parentdev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); 
 | 
				
			||||||
	    if (parentdev != NULL) {
 | 
						    if (parentdev != NULL) {
 | 
				
			||||||
	      char const *p;
 | 
						      char const *p;
 | 
				
			||||||
| 
						 | 
					@ -387,9 +458,12 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
	      if (num_things < max_things) {
 | 
						      if (num_things < max_things) {
 | 
				
			||||||
	        things[num_things].vid = vid;
 | 
						        things[num_things].vid = vid;
 | 
				
			||||||
	        things[num_things].pid = pid;
 | 
						        things[num_things].pid = pid;
 | 
				
			||||||
 | 
						        SAFE_STRCPY (things[num_things].card_name, pattrs_id);
 | 
				
			||||||
 | 
						        SAFE_STRCPY (things[num_things].card_number, pattrs_number);
 | 
				
			||||||
	        SAFE_STRCPY (things[num_things].product, udev_device_get_sysattr_value(parentdev,"product"));
 | 
						        SAFE_STRCPY (things[num_things].product, udev_device_get_sysattr_value(parentdev,"product"));
 | 
				
			||||||
	        SAFE_STRCPY (things[num_things].devnode_sound, devnode);
 | 
						        SAFE_STRCPY (things[num_things].devnode_sound, devnode);
 | 
				
			||||||
	        SAFE_STRCPY (things[num_things].devnode_usb, udev_device_get_devnode(parentdev));
 | 
						        SAFE_STRCPY (things[num_things].devnode_usb, udev_device_get_devnode(parentdev));
 | 
				
			||||||
 | 
						        strlcpy (things[num_things].devpath, card_devpath, sizeof(things[num_things].devpath));
 | 
				
			||||||
	        num_things++;
 | 
						        num_things++;
 | 
				
			||||||
	      }
 | 
						      }
 | 
				
			||||||
	      udev_device_unref(parentdev);
 | 
						      udev_device_unref(parentdev);
 | 
				
			||||||
| 
						 | 
					@ -414,8 +488,7 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
	udev_enumerate_scan_devices(enumerate);
 | 
						udev_enumerate_scan_devices(enumerate);
 | 
				
			||||||
	devices = udev_enumerate_get_list_entry(enumerate);
 | 
						devices = udev_enumerate_get_list_entry(enumerate);
 | 
				
			||||||
	udev_list_entry_foreach(dev_list_entry, devices) {
 | 
						udev_list_entry_foreach(dev_list_entry, devices) {
 | 
				
			||||||
	  const char *path;
 | 
						  const char *path = udev_list_entry_get_name(dev_list_entry);
 | 
				
			||||||
	  path = udev_list_entry_get_name(dev_list_entry);
 | 
					 | 
				
			||||||
	  dev = udev_device_new_from_syspath(udev, path);
 | 
						  dev = udev_device_new_from_syspath(udev, path);
 | 
				
			||||||
	  char const *devnode = udev_device_get_devnode(dev);
 | 
						  char const *devnode = udev_device_get_devnode(dev);
 | 
				
			||||||
	  if (devnode != NULL) {
 | 
						  if (devnode != NULL) {
 | 
				
			||||||
| 
						 | 
					@ -448,6 +521,7 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
	        SAFE_STRCPY (things[num_things].product, udev_device_get_sysattr_value(parentdev,"product"));
 | 
						        SAFE_STRCPY (things[num_things].product, udev_device_get_sysattr_value(parentdev,"product"));
 | 
				
			||||||
	        SAFE_STRCPY (things[num_things].devnode_hidraw, devnode);
 | 
						        SAFE_STRCPY (things[num_things].devnode_hidraw, devnode);
 | 
				
			||||||
	        SAFE_STRCPY (things[num_things].devnode_usb, usb);
 | 
						        SAFE_STRCPY (things[num_things].devnode_usb, usb);
 | 
				
			||||||
 | 
						        SAFE_STRCPY (things[num_things].devpath, udev_device_get_devpath(dev));
 | 
				
			||||||
	        num_things++;
 | 
						        num_things++;
 | 
				
			||||||
	      }
 | 
						      }
 | 
				
			||||||
	      udev_device_unref(parentdev);
 | 
						      udev_device_unref(parentdev);
 | 
				
			||||||
| 
						 | 
					@ -461,6 +535,8 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
 * Seeing the form /dev/snd/pcmC4D0p will be confusing to many because we
 | 
					 * Seeing the form /dev/snd/pcmC4D0p will be confusing to many because we
 | 
				
			||||||
 * would generally something like plughw:4,0 for in the direwolf configuration file.
 | 
					 * would generally something like plughw:4,0 for in the direwolf configuration file.
 | 
				
			||||||
 * Construct the more familiar form.
 | 
					 * Construct the more familiar form.
 | 
				
			||||||
 | 
					 * Previously we only used the numeric form.  In version 1.6, the name is listed as well
 | 
				
			||||||
 | 
					 * and we describe how to assign names based on the physical USB socket for repeatability.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	regex_t pcm_re;
 | 
						regex_t pcm_re;
 | 
				
			||||||
| 
						 | 
					@ -481,6 +557,7 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
	    substr_se (c, things[i].devnode_sound, match[1].rm_so, match[1].rm_eo);
 | 
						    substr_se (c, things[i].devnode_sound, match[1].rm_so, match[1].rm_eo);
 | 
				
			||||||
	    substr_se (d, things[i].devnode_sound, match[2].rm_so, match[2].rm_eo);
 | 
						    substr_se (d, things[i].devnode_sound, match[2].rm_so, match[2].rm_eo);
 | 
				
			||||||
	    snprintf (things[i].plughw, sizeof(things[i].plughw), "plughw:%s,%s", c, d);
 | 
						    snprintf (things[i].plughw, sizeof(things[i].plughw), "plughw:%s,%s", c, d);
 | 
				
			||||||
 | 
						    snprintf (things[i].plughw2, sizeof(things[i].plughw), "plughw:%s,%s", things[i].card_name, d);
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,11 +570,16 @@ int cm108_inventory (struct thing_s *things, int max_things)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Name:	cm108_find_ptt
 | 
					 * Name:	cm108_find_ptt
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Purpose:	Try to find /dev/hidraw corresponding to plughw:n,n
 | 
					 * Purpose:	Try to find /dev/hidraw corresponding to a USB audio "card."
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Inputs:	output_audio_device
 | 
					 * Inputs:	output_audio_device
 | 
				
			||||||
 *				- Device name used in the ADEVICE configuration.
 | 
					 *				- Used in the ADEVICE configuration.
 | 
				
			||||||
 *				  This would generally be something like plughw:1,0
 | 
					 *				  This can take many forms such as:
 | 
				
			||||||
 | 
					 *					surround41:CARD=Fred,DEV=0
 | 
				
			||||||
 | 
					 *					surround41:Fred,0
 | 
				
			||||||
 | 
					 *					surround41:Fred
 | 
				
			||||||
 | 
					 *					plughw:2,3
 | 
				
			||||||
 | 
					 *				  In our case we just need to extract the card number or name.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		ptt_device_size	- Size of result area to avoid buffer overflow.
 | 
					 *		ptt_device_size	- Size of result area to avoid buffer overflow.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -514,15 +596,46 @@ void cm108_find_ptt (char *output_audio_device, char *ptt_device,  int ptt_devic
 | 
				
			||||||
	int num_things;
 | 
						int num_things;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//dw_printf ("DEBUG: cm108_find_ptt('%s')\n", output_audio_device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	strlcpy (ptt_device, "", ptt_device_size);
 | 
						strlcpy (ptt_device, "", ptt_device_size);
 | 
				
			||||||
	num_things = cm108_inventory (things, MAXX_THINGS);
 | 
						num_things = cm108_inventory (things, MAXX_THINGS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < num_things; i++) {
 | 
						regex_t sound_re;
 | 
				
			||||||
 | 
						char emsg[100];
 | 
				
			||||||
	  if (GOOD_DEVICE(things[i].vid,things[i].pid) ) {
 | 
						int e = regcomp (&sound_re, ".+:(CARD=)?([A-Za-z0-9_]+)(,.*)?", REG_EXTENDED);
 | 
				
			||||||
	    if (strcmp(output_audio_device, things[i].plughw) == 0) {
 | 
						if (e) {
 | 
				
			||||||
	      strlcpy (ptt_device, things[i].devnode_hidraw, ptt_device_size);
 | 
						  regerror (e, &sound_re, emsg, sizeof(emsg));
 | 
				
			||||||
 | 
						  text_color_set(DW_COLOR_ERROR);
 | 
				
			||||||
 | 
						  dw_printf("INTERNAL ERROR:  %s:%d: %s\n", __FILE__, __LINE__, emsg);
 | 
				
			||||||
 | 
						  return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char num_or_name[64];
 | 
				
			||||||
 | 
						strcpy (num_or_name, "");
 | 
				
			||||||
 | 
						regmatch_t sound_match[4];
 | 
				
			||||||
 | 
						if (regexec (&sound_re, output_audio_device, 4, sound_match, 0) == 0) {
 | 
				
			||||||
 | 
						  substr_se (num_or_name, output_audio_device, sound_match[2].rm_so, sound_match[2].rm_eo);
 | 
				
			||||||
 | 
						  //dw_printf ("DEBUG: Got '%s' from '%s'\n", num_or_name, output_audio_device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strlen(num_or_name) == 0) {
 | 
				
			||||||
 | 
						  text_color_set(DW_COLOR_ERROR);
 | 
				
			||||||
 | 
						  dw_printf ("Could not extract card number or name from %s\n", output_audio_device);
 | 
				
			||||||
 | 
						  dw_printf ("Can't automatically find matching HID for PTT.\n");
 | 
				
			||||||
 | 
						  return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < num_things; i++) {
 | 
				
			||||||
 | 
						  //dw_printf ("DEBUG: i=%d, card_name='%s', card_number='%s'\n", i, things[i].card_name, things[i].card_number);
 | 
				
			||||||
 | 
						  if (strcmp(num_or_name,things[i].card_name) == 0 || strcmp(num_or_name,things[i].card_number) == 0) {
 | 
				
			||||||
 | 
						    //dw_printf ("DEBUG: success! returning '%s'\n", things[i].devnode_hidraw);
 | 
				
			||||||
 | 
						    strlcpy (ptt_device, things[i].devnode_hidraw, ptt_device_size);
 | 
				
			||||||
 | 
						    if ( ! GOOD_DEVICE(things[i].vid,things[i].pid) ) {
 | 
				
			||||||
 | 
						      text_color_set(DW_COLOR_ERROR);
 | 
				
			||||||
 | 
						      dw_printf ("Warning: USB audio card %s (%s) is not a device known to work with GPIO PTT.\n",
 | 
				
			||||||
 | 
									things[i].card_number, things[i].card_name);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    return;
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue