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 <[email protected]>
wrote:
From: Santiago Palomino Sanchez-Manjavacas <[email protected]>
Subject: Re: [Pyusb-users] Mapping usb serial devices to device filenames
To: [email protected], [email protected]
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)
<[email protected]> 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)
> <[email protected] <mailto:[email protected]>> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/pyusb-users
------------------------------------------------------------------------------
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
_______________________________________________
Pyusb-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pyusb-users