From: Sarah M. <iku...@ya...> - 2009-06-17 16:00:10
|
You can also search the /sys/devices/ tree. On my system (SUSE 11.1, Linux 2.6), all usb devices appear in /sys/devices/pci0000:00/ subdirectories. The particular hardware-to-subdirectory mapping varies by boot, but there's lots of configuration information if you go sufficiently leafward in the tree, including vendorID, productID, /dev/ entry, and available configurations, interfaces, etc. The exact info and placement which shows up depends on the driver / hardware which you're using. I've three different USB/RS232 adapters, and have to identify each one in a different way - but I use the /sys/devices tree for all of them. Here's some code to do the search. Hopefully the comments and doc-strings are enough documentation to get it working. (You'll probably want to change all "runlog" calls to print statements since that references my own logging utility.) def sercheck(dirname,subdirstem,SerNumRE,Interface): '''Check if a given sysfs directory matches regular expression SerNumRE dirname is the full path to the subdirectory of /sys/devices/ containing the description of the device. subdirstem is a partial path to be used in forming the names of further subdirectories. SerNumRE is a regular expression describing the serial number of the target device Interface is a digit indexing the appropriate USB interface which corresponds to thte target scope. This function is designed for the USB-16COM-RM 16-port USB/RS-232 hub, but also works for the SeaLevel SeaLink #2113 USB/RS-232 adapter.''' if os.path.isfile(dirname+'/serial'): serialfile=open(dirname+'/serial',mode='r') sernum=serialfile.readline() serialfile.close() if SerNumRE.match(sernum): intflist=shortdir(dirname, re.escape(subdirstem+':1.'+Interface)) intfdir=intflist[0] foundlist=shortdir(dirname+'/'+intfdir, r'ttyUSB[0-9]+') foundat=foundlist[0] return foundat return False def MoxaCheck(dirname,subdirstem,DesiredName,rl): '''Check if a given sysfs directory matches the target scope number. dirname is the full path to the subdirectory of /sys/devices/ containing the description of the device. subdirstem is a partial path to be used in forming the names of further subdirectories. DesiredName is the name of a directory to seek on the prospective scope. The prospective scope is assumed to be the correct one iff a directory with this name is found on it. This function is designed for the MOXA UPort 1450I 4-port USB/RS-232 hub.''' #first check to see if this is a MOXA hub. if not os.path.isfile(dirname+'/manufacturer'): return False manufile=open(dirname+'/manufacturer',mode='r') manu=manufile.readline() manufile.close() if not manu.startswith('MOXA'): return False #now know we have a MOXA hub - look in its interface dir for subdirectories corresponding to the /dev entries intflist=shortdir(dirname, re.escape(subdirstem+':1.0')) intfdir=intflist[0] portlist=shortdir(dirname+'/'+intfdir, r'ttyMXUSB[0-9]+') #reorder portlist as a guess at the best order to search for the scope num=int(DesiredName[-1]) #assumes scopes 1-8 are attached to the MOXA hubs in order, 1-4 on one, 5-8 on the other num=(num-1)%4 #get the remainder modulo 4 while num!=int((portlist[0])[-1])%4: port=portlist.pop(-1) portlist.insert(0,port) for port in portlist: DevToCheck=port #contact this scope - assuming it's connected try: tempScope=SerScope((0,'TEMP','/dev/'+DevToCheck),rl,set([])) fileset=tempScope.ask('FILES:DIR?') if '"'+DesiredName+'"' in fileset: #check if this scope has the desired directory tempScope.close() return DevToCheck rl.log(2,'%s is a scope, but not the target one.'%DevToCheck) except IOError,msg: rl.log(2,'%s is not a scope, gave message %s'%(DevToCheck,msg)) return False def HubSearch1Tier(Target,IDmode,path,prefix,tier,Interface,runlog): '''Recursively searches for an RS-232 port attached via a USB-RS-232 hub. declaration: HubSearch1Tier(Target,IDmode,path,tier,runlog) Target - the identification string (Serial number or directory name) for the target scope IDmode - 1 or 3, depending on the hardware used to connect to the scope path - the base path where the search should begin prefix - portion of valid subdirectories which reflects higher-level search path tier - integer between 1 and 7, inclusive. Tier 1 is the root USB hub. Tier 7 is the leafmost possible device. Interface - 0 to 7 if the device interface specifies which scope to contact; -1 otherwise runlog - runlog.runlog instance for message logging This function is only intended to be called by USBRS232HubSearch() and by itself. This routine does a depth-first search.''' runlog.log(2,'Searching for %s in %s'%(Target,path)) #USB specifies max of 7 tiers. if tier==1: #This is the root hub, Tier 1. Is USB always in 0000:00:1d.x ?; get USB directories pattern=r'0000:00:1d\.[0-7]' #pattern is passed to shortdir to find directories for the next tier elif tier==2: #e.g. path='/sys/devices/pci0000:00/0000:00:1d.0' [Tier 2] pattern=r'usb[1-7]' #0 is hub controller itself? elif tier==3: #e.g. path='/sys/devices/pci0000:00/0000:00:1d.0/usb1/1-2' [Tier 3] pattern=prefix+r'-[1-7]' elif tier in [4,5,6,7]: #Tier 4 e.g. path='/sys/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2.1' #Tier 5 e.g. path='/sys/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2.1/1-2.1.7' #Tier 6 e.g. '/sys/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2.1/1-2.1.7/1-2.1.7.4' #Tier 7 e.g. '/sys/devices/pci0000:00/0000:00:1d.0/usb1/1-2/1-2.1/1-2.1.7/1-2.1.7.4.5' pattern=prefix+r'\.[1-7]' else: raise ValueError,'Tier must be an integer between 1 and 7, inclusive, not %f'%tier dirlist=shortdir(path,pattern) for subdir in dirlist: newpath=path+'/'+subdir if tier==2: newprefix=subdir[3] #1 char (usually?) for bus number else: newprefix=subdir if tier>=3: #can't attach serial scopes at tiers 1-3 if IDmode==1: foundat=sercheck(newpath,newprefix,Target,Interface) else: #IDmode==3 foundat=MoxaCheck(newpath,newprefix,Target,runlog) if foundat: runlog.log(2,'%s on %s.'%(Target, foundat)) return foundat if tier<7: foundat=HubSearch1Tier(Target,IDmode,newpath,newprefix,tier+1,Interface,runlog) if foundat: return foundat return False def USBRS232HubSearch(TargetSerNum,runlog): '''Searches for an RS-232 port attached via a USB-RS-232 hub. declaration: USBRS232HubSearch(TargetSerNum,runlog) TargetSerNum - serial number of the hardware USB/RS-232 converter for the target scope. The serial number of the leafmost USB device should be xxx, where the input TargetSerNum is SERxxxD. D should be the USB interface for the RS-232 port and must be between 0 and 7. runlog - runlog.runlog instance for message logging''' if TargetSerNum=='TEMP': #temporary serial number generated by MoxaCheck() to search for a scope raise IOError, "No scope at target location." runlog.log(0,'Searching for %s'%TargetSerNum) basepath='/sys/devices/pci0000:00' if TargetSerNum.startswith('SER'): #16-port USB/RS-232 hub or 1-port SeaLevel SeaLink adapter; ID by adapter's serial # & interface TSNre=re.compile(r'\ASER\S+?[0-7]\Z') if not TSNre.match(TargetSerNum): raise ValueError, 'Invalid serial number %s'%TargetSerNum #serial number devstr=TargetSerNum[3:len(TargetSerNum)-1] SerNumRE=re.compile(devstr+r'\s*') Interface=TargetSerNum[len(TargetSerNum)-1] #single-character interface num return HubSearch1Tier(SerNumRE,1,basepath,'',1,Interface,runlog) elif TargetSerNum.startswith('COM'): #RS-232 port directly on the computer return '/dev/ttyS0' #This might even be general - anything's possible elif TargetSerNum.startswith('moxa'): #MOXA UPort 1450I 4-port USB/RS-232 hub DesiredName=TargetSerNum[4:] return HubSearch1Tier(DesiredName,3,basepath,'',1,-1,runlog) else: raise ValueError, 'Invalid serial number %s'%TargetSerNum Your milage may vary. -Sarah --- On Wed, 6/17/09, Santiago Palomino Sanchez-Manjavacas <sp...@gm...> wrote: From: Santiago Palomino Sanchez-Manjavacas <sp...@gm...> Subject: Re: [Pyusb-users] Mapping usb serial devices to device filenames To: Bre...@et..., pyu...@li... Date: Wednesday, June 17, 2009, 3:08 AM Hi, This is based on a script that I downloaded with Porus. I think it was called porustest.py: http://prdownload.berlios.de/porus/porus-0.1.1.tgz I recommend you to test it. It has a command interface that is useful for debugging. Self is the command interpreter object, def getdevs(): """Returns a flat array of configs on all busses -- ie an array of tuples of (bus,dev,conf). Array is guaranteed to be sorted by bus and dev. Used for giving numbers to configs""" rtn=[] for b in usb.busses(): for d in b.devices: for c in d.configurations: rtn.append((b,d,c)) return rtn I don't know much about the serial part, but I would look into how serial.Serial(port) is implemented. May be you need to change it a bit if you want to open a device by PID and VID. I guess that it opens the device and claims an interface, but I haven't used that library. I hope this helps. Ah, I forgot On Wed, Jun 17, 2009 at 9:27 AM, Brendan Simon (eTRIX) <Bre...@et...> wrote: Thanks Santiago :) Unfortunately I'm new to usb so it's not making too much sense at the moment. What is the class object that self is referring to here ? Is getdevs() your own function or a standard os function ? Presumably getdevs calls something like usb.busses() somewhere ? I don't see how this gives me the name of the serial device (eg. /dev/cu.usbmodem0001) that I can then reference with pyserial Serial() function. example: port = '/dev/cu.usbmodem0001' # need to auto detect/determine this ser = serial.Serial( port ) Thanks Brendan. Santiago Palomino Sanchez-Manjavacas wrote: > Well, you can use the device VID and PID to select which device to open. > I use something like: > > def do_d(self, args): > if self.devh is not None: > self.do_close('') > #ls > if self.devh is None: > self.devs=getdevs() > shortlist(self.devs) > dn = -1; > index = 0; > for d in self.devs: > if (d[1].idVendor == 0xFFFF and d[1].idProduct == 0x0000): > dn = index; > index = index + 1; > if(dn == -1): > return 1 > self.curdev=self.devs[dn] > self.devh=self.curdev[1].open() > self.devn=dn > self.devh.setConfiguration(self.curdev[2]) > > self.devh.claimInterface(self.curdev[2].interfaces[0][0]) > self.devh.setAltInterface(0) > > > > On Wed, Jun 17, 2009 at 7:14 AM, Brendan Simon (eTRIX) > <Bre...@et... <mailto:Bre...@et...>> wrote: > > I have a device with a usb connection that presents itself as a serial > device to operating system (OS X). > It appears as /dev/cu.usbmodem0001 and /dev/tty.usbmodem0001 on the > filesystem when the device is plugged in. > > I can successfully detect the device USB Vendor ID and Product ID using > pyusb :) > > Now I have to use pyserial to talk to the device -- which I have > successfully done by opening the serial port with a hard coded device > filename (/dev/cu.usbmodem0001). > > There must be some way for me to use the pyusb information to be able to > determine the appropriate device filename to open with pyusb. > > Does anyone know how to do this or have any suggestions ??? > > Thanks, Brendan. -----Inline Attachment Follows----- ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects -----Inline Attachment Follows----- _______________________________________________ Pyusb-users mailing list Pyu...@li... https://lists.sourceforge.net/lists/listinfo/pyusb-users |