Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: devil/devil/utils/find_usb_devices.py

Issue 1823193002: add GetBattorPathFromPhoneSerial to find_usb_devices (Closed) Base URL: git@github.com:catapult-project/catapult@master
Patch Set: add new feature to add a fixed mapping Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright 2016 The Chromium Authors. All rights reserved. 2 # Copyright 2016 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import re 6 import re
7 import sys 7 import sys
8 import argparse 8 import argparse
9 import json
10 import collections
9 11
12 from devil import base_error
10 from devil.utils import cmd_helper 13 from devil.utils import cmd_helper
14 from devil.utils import usb_hubs
11 from devil.utils import lsusb 15 from devil.utils import lsusb
12 16
13 # Note: In the documentation below, "virtual port" refers to the port number 17 # Note: In the documentation below, "virtual port" refers to the port number
14 # as observed by the system (e.g. by usb-devices) and "physical port" refers 18 # as observed by the system (e.g. by usb-devices) and "physical port" refers
15 # to the physical numerical label on the physical port e.g. on a USB hub. 19 # to the physical numerical label on the physical port e.g. on a USB hub.
16 # The mapping between virtual and physical ports is not always the identity 20 # The mapping between virtual and physical ports is not always the identity
17 # (e.g. the port labeled "1" on a USB hub does not always show up as "port 1" 21 # (e.g. the port labeled "1" on a USB hub does not always show up as "port 1"
18 # when you plug something into it) but, as far as we are aware, the mapping 22 # when you plug something into it) but, as far as we are aware, the mapping
19 # between virtual and physical ports is always the same for a given 23 # between virtual and physical ports is always the same for a given
20 # model of USB hub. When "port number" is referenced without specifying, it 24 # model of USB hub. When "port number" is referenced without specifying, it
(...skipping 25 matching lines...) Expand all
46 50
47 def GetBattorList(device_tree_map): 51 def GetBattorList(device_tree_map):
48 return [x for x in GetTTYList() if IsBattor(x, device_tree_map)] 52 return [x for x in GetTTYList() if IsBattor(x, device_tree_map)]
49 53
50 54
51 def IsBattor(tty_string, device_tree_map): 55 def IsBattor(tty_string, device_tree_map):
52 (bus, device) = GetBusDeviceFromTTY(tty_string) 56 (bus, device) = GetBusDeviceFromTTY(tty_string)
53 node = device_tree_map[bus].FindDeviceNumber(device) 57 node = device_tree_map[bus].FindDeviceNumber(device)
54 return 'Future Technology Devices International' in node.desc 58 return 'Future Technology Devices International' in node.desc
55 59
60 def GetBattorSerialNumbers(device_tree_map):
61 for x in GetTTYList():
62 if IsBattor(x, device_tree_map):
63 (bus, device) = GetBusDeviceFromTTY(x)
64 devnode = device_tree_map[bus].FindDeviceNumber(device)
65 yield devnode.serial
66
67 class BattorError(base_error.BaseError):
68 pass
56 69
57 # Class to identify nodes in the USB topology. USB topology is organized as 70 # Class to identify nodes in the USB topology. USB topology is organized as
58 # a tree. 71 # a tree.
59 class USBNode(object): 72 class USBNode(object):
60 def __init__(self): 73 def __init__(self):
61 self._port_to_node = {} 74 self._port_to_node = {}
62 75
63 @property 76 @property
64 def desc(self): 77 def desc(self):
65 raise NotImplementedError 78 raise NotImplementedError
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 257
245 258
246 _T_LINE_REGEX = re.compile(r'T: Bus=(?P<bus>\d{2}) Lev=(?P<lev>\d{2}) ' 259 _T_LINE_REGEX = re.compile(r'T: Bus=(?P<bus>\d{2}) Lev=(?P<lev>\d{2}) '
247 r'Prnt=(?P<prnt>\d{2,3}) Port=(?P<port>\d{2}) ' 260 r'Prnt=(?P<prnt>\d{2,3}) Port=(?P<port>\d{2}) '
248 r'Cnt=(?P<cnt>\d{2}) Dev#=(?P<dev>.{3}) .*') 261 r'Cnt=(?P<cnt>\d{2}) Dev#=(?P<dev>.{3}) .*')
249 262
250 _S_LINE_REGEX = re.compile(r'S: SerialNumber=(?P<serial>.*)') 263 _S_LINE_REGEX = re.compile(r'S: SerialNumber=(?P<serial>.*)')
251 _LSUSB_BUS_DEVICE_RE = re.compile(r'^Bus (\d{3}) Device (\d{3}): (.*)') 264 _LSUSB_BUS_DEVICE_RE = re.compile(r'^Bus (\d{3}) Device (\d{3}): (.*)')
252 265
253 266
254 def GetBusNumberToDeviceTreeMap(fast=False): 267 def GetBusNumberToDeviceTreeMap(fast=False):
rnephew (Reviews Here) 2016/03/25 00:17:52 Since everywhere seems to use fast=True, should th
255 """Gets devices currently attached. 268 """Gets devices currently attached.
256 269
257 Args: 270 Args:
258 fast [bool]: whether to do it fast (only get description, not 271 fast [bool]: whether to do it fast (only get description, not
259 the whole dictionary, from lsusb) 272 the whole dictionary, from lsusb)
260 273
261 Returns: 274 Returns:
262 map of {bus number: bus object} 275 map of {bus number: bus object}
263 where the bus object has all the devices attached to it in a tree. 276 where the bus object has all the devices attached to it in a tree.
264 """ 277 """
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 match = _S_LINE_REGEX.match(line) 317 match = _S_LINE_REGEX.match(line)
305 if match: 318 if match:
306 if bus_num == -1: 319 if bus_num == -1:
307 raise ValueError('S line appears before T line in input file') 320 raise ValueError('S line appears before T line in input file')
308 # put the serial number in the device 321 # put the serial number in the device
309 tree[bus_num].FindDeviceNumber(device_num).serial = match.group('serial') 322 tree[bus_num].FindDeviceNumber(device_num).serial = match.group('serial')
310 323
311 return tree 324 return tree
312 325
313 326
314 class HubType(object):
315 def __init__(self, id_func, port_mapping):
316 """Defines a type of hub.
317
318 Args:
319 id_func: [USBNode -> bool] is a function that can be run on a node
320 to determine if the node represents this type of hub.
321 port_mapping: [dict(int:(int|dict))] maps virtual to physical port
322 numbers. For instance, {3:1, 1:2, 2:3} means that virtual port 3
323 corresponds to physical port 1, virtual port 1 corresponds to physical
324 port 2, and virtual port 2 corresponds to physical port 3. In the
325 case of hubs with "internal" topology, this is represented by nested
326 maps. For instance, {1:{1:1,2:2},2:{1:3,2:4}} means, e.g. that the
327 device plugged into physical port 3 will show up as being connected
328 to port 1, on a device which is connected to port 2 on the hub.
329 """
330 self._id_func = id_func
331 # v2p = "virtual to physical" ports
332 self._v2p_port = port_mapping
333
334 def IsType(self, node):
335 """Determines if the given Node is a hub of this type.
336
337 Args:
338 node: [USBNode] Node to check.
339 """
340 return self._id_func(node)
341
342 def GetPhysicalPortToNodeTuples(self, node):
343 """Gets devices connected to the physical ports on a hub of this type.
344
345 Args:
346 node: [USBNode] Node representing a hub of this type.
347
348 Yields:
349 A series of (int, USBNode) tuples giving a physical port
350 and the USBNode connected to it.
351
352 Raises:
353 ValueError: If the given node isn't a hub of this type.
354 """
355 if self.IsType(node):
356 for res in self._GppHelper(node, self._v2p_port):
357 yield res
358 else:
359 raise ValueError('Node must be a hub of this type')
360
361 def _GppHelper(self, node, mapping):
362 """Helper function for GetPhysicalPortToNodeMap.
363
364 Gets devices connected to physical ports, based on device tree
365 rooted at the given node and the mapping between virtual and physical
366 ports.
367
368 Args:
369 node: [USBNode] Root of tree to search for devices.
370 mapping: [dict] Mapping between virtual and physical ports.
371
372 Yields:
373 A series of (int, USBNode) tuples giving a physical port
374 and the Node connected to it.
375 """
376 for (virtual, physical) in mapping.iteritems():
377 if node.HasPort(virtual):
378 if isinstance(physical, dict):
379 for res in self._GppHelper(node.PortToDevice(virtual), physical):
380 yield res
381 else:
382 yield (physical, node.PortToDevice(virtual))
383
384
385 def GetHubsOnBus(bus, hub_types): 327 def GetHubsOnBus(bus, hub_types):
386 """Scans for all hubs on a bus of given hub types. 328 """Scans for all hubs on a bus of given hub types.
387 329
388 Args: 330 Args:
389 bus: [USBNode] Bus object. 331 bus: [USBNode] Bus object.
390 hub_types: [iterable(HubType)] Possible types of hubs. 332 hub_types: [iterable(usb_hubs.HubType)] Possible types of hubs.
391 333
392 Yields: 334 Yields:
393 Sequence of tuples representing (hub, type of hub) 335 Sequence of tuples representing (hub, type of hub)
394 """ 336 """
395 for device in bus.AllNodes(): 337 for device in bus.AllNodes():
396 for hub_type in hub_types: 338 for hub_type in hub_types:
397 if hub_type.IsType(device): 339 if hub_type.IsType(device):
398 yield (device, hub_type) 340 yield (device, hub_type)
399 341
400 342
401 def GetPhysicalPortToNodeMap(hub, hub_type): 343 def GetPhysicalPortToNodeMap(hub, hub_type):
402 """Gets physical-port:node mapping for a given hub. 344 """Gets physical-port:node mapping for a given hub.
403 Args: 345 Args:
404 hub: [USBNode] Hub to get map for. 346 hub: [USBNode] Hub to get map for.
405 hub_type: [HubType] Which type of hub it is. 347 hub_type: [usb_hubs.HubType] Which type of hub it is.
406 348
407 Returns: 349 Returns:
408 Dict of {physical port: node} 350 Dict of {physical port: node}
409 """ 351 """
410 port_device = hub_type.GetPhysicalPortToNodeTuples(hub) 352 port_device = hub_type.GetPhysicalPortToNodeTuples(hub)
411 return {port: device for (port, device) in port_device} 353 return {port: device for (port, device) in port_device}
412 354
413 355
414 def GetPhysicalPortToBusDeviceMap(hub, hub_type): 356 def GetPhysicalPortToBusDeviceMap(hub, hub_type):
415 """Gets physical-port:(bus#, device#) mapping for a given hub. 357 """Gets physical-port:(bus#, device#) mapping for a given hub.
416 Args: 358 Args:
417 hub: [USBNode] Hub to get map for. 359 hub: [USBNode] Hub to get map for.
418 hub_type: [HubType] Which type of hub it is. 360 hub_type: [usb_hubs.HubType] Which type of hub it is.
419 361
420 Returns: 362 Returns:
421 Dict of {physical port: (bus number, device number)} 363 Dict of {physical port: (bus number, device number)}
422 """ 364 """
423 port_device = hub_type.GetPhysicalPortToNodeTuples(hub) 365 port_device = hub_type.GetPhysicalPortToNodeTuples(hub)
424 return {port: (device.bus_num, device.device_num) 366 return {port: (device.bus_num, device.device_num)
425 for (port, device) in port_device} 367 for (port, device) in port_device}
426 368
427 369
428 def GetPhysicalPortToSerialMap(hub, hub_type): 370 def GetPhysicalPortToSerialMap(hub, hub_type):
429 """Gets physical-port:serial# mapping for a given hub. 371 """Gets physical-port:serial# mapping for a given hub.
430 Args: 372 Args:
431 hub: [USBNode] Hub to get map for. 373 hub: [USBNode] Hub to get map for.
432 hub_type: [HubType] Which type of hub it is. 374 hub_type: [usb_hubs.HubType] Which type of hub it is.
433 375
434 Returns: 376 Returns:
435 Dict of {physical port: serial number)} 377 Dict of {physical port: serial number)}
436 """ 378 """
437 port_device = hub_type.GetPhysicalPortToNodeTuples(hub) 379 port_device = hub_type.GetPhysicalPortToNodeTuples(hub)
438 return {port: device.serial 380 return {port: device.serial
439 for (port, device) in port_device 381 for (port, device) in port_device
440 if device.serial} 382 if device.serial}
441 383
442 384
443 def GetPhysicalPortToTTYMap(device, hub_type): 385 def GetPhysicalPortToTTYMap(device, hub_type):
444 """Gets physical-port:tty-string mapping for a given hub. 386 """Gets physical-port:tty-string mapping for a given hub.
445 Args: 387 Args:
446 hub: [USBNode] Hub to get map for. 388 hub: [USBNode] Hub to get map for.
447 hub_type: [HubType] Which type of hub it is. 389 hub_type: [usb_hubs.HubType] Which type of hub it is.
448 390
449 Returns: 391 Returns:
450 Dict of {physical port: tty-string)} 392 Dict of {physical port: tty-string)}
451 """ 393 """
452 port_device = hub_type.GetPhysicalPortToNodeTuples(device) 394 port_device = hub_type.GetPhysicalPortToNodeTuples(device)
453 bus_device_to_tty = GetBusDeviceToTTYMap() 395 bus_device_to_tty = GetBusDeviceToTTYMap()
454 return {port: bus_device_to_tty[(device.bus_num, device.device_num)] 396 return {port: bus_device_to_tty[(device.bus_num, device.device_num)]
455 for (port, device) in port_device 397 for (port, device) in port_device
456 if (device.bus_num, device.device_num) in bus_device_to_tty} 398 if (device.bus_num, device.device_num) in bus_device_to_tty}
457 399
458 400
459 def CollectHubMaps(hub_types, map_func, device_tree_map=None, fast=False): 401 def CollectHubMaps(hub_types, map_func, device_tree_map=None, fast=False):
460 """Runs a function on all hubs in the system and collects their output. 402 """Runs a function on all hubs in the system and collects their output.
461 403
462 Args: 404 Args:
463 hub_types: [HubType] List of possible hub types. 405 hub_types: [usb_hubs.HubType] List of possible hub types.
464 map_func: [string] Function to run on each hub. 406 map_func: [string] Function to run on each hub.
465 device_tree: Previously constructed device tree map, if any. 407 device_tree: Previously constructed device tree map, if any.
466 fast: Whether to construct device tree fast, if not already provided 408 fast: Whether to construct device tree fast, if not already provided
467 409
468 Yields: 410 Yields:
469 Sequence of dicts of {physical port: device} where the type of 411 Sequence of dicts of {physical port: device} where the type of
470 device depends on the ident keyword. Each dict is a separate hub. 412 device depends on the ident keyword. Each dict is a separate hub.
471 """ 413 """
472 if device_tree_map is None: 414 if device_tree_map is None:
473 device_tree_map = GetBusNumberToDeviceTreeMap(fast=fast) 415 device_tree_map = GetBusNumberToDeviceTreeMap(fast=fast)
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 return result 487 return result
546 488
547 489
548 # This dictionary described the mapping between physical and 490 # This dictionary described the mapping between physical and
549 # virtual ports on a Plugable 7-Port Hub (model USB2-HUB7BC). 491 # virtual ports on a Plugable 7-Port Hub (model USB2-HUB7BC).
550 # Keys are the virtual ports, values are the physical port. 492 # Keys are the virtual ports, values are the physical port.
551 # The entry 4:{1:4, 2:3, 3:2, 4:1} indicates that virtual port 493 # The entry 4:{1:4, 2:3, 3:2, 4:1} indicates that virtual port
552 # 4 connects to another 'virtual' hub that itself has the 494 # 4 connects to another 'virtual' hub that itself has the
553 # virtual-to-physical port mapping {1:4, 2:3, 3:2, 4:1}. 495 # virtual-to-physical port mapping {1:4, 2:3, 3:2, 4:1}.
554 496
555 PLUGABLE_7PORT_LAYOUT = {1:7,
556 2:6,
557 3:5,
558 4:{1:4, 2:3, 3:2, 4:1}}
559 497
560 def TestUSBTopologyScript(): 498 def TestUSBTopologyScript():
561 """Test display and hub identification.""" 499 """Test display and hub identification."""
562 # Identification criteria for Plugable 7-Port Hub 500 # Identification criteria for Plugable 7-Port Hub
563 def _is_plugable_7port_hub(node):
564 """Check if a node is a Plugable 7-Port Hub
565 (Model USB2-HUB7BC)
566 The topology of this device is a 4-port hub,
567 with another 4-port hub connected on port 4.
568 """
569 if not isinstance(node, USBDeviceNode):
570 return False
571 if '4-Port HUB' not in node.desc:
572 return False
573 if not node.HasPort(4):
574 return False
575 return '4-Port HUB' in node.PortToDevice(4).desc
576
577 plugable_7port = HubType(_is_plugable_7port_hub,
578 PLUGABLE_7PORT_LAYOUT)
579 print '==== USB TOPOLOGY SCRIPT TEST ====' 501 print '==== USB TOPOLOGY SCRIPT TEST ===='
580 502
581 # Display devices 503 # Display devices
582 print '==== DEVICE DISPLAY ====' 504 print '==== DEVICE DISPLAY ===='
583 device_trees = GetBusNumberToDeviceTreeMap(fast=True) 505 device_trees = GetBusNumberToDeviceTreeMap(fast=True)
584 for device_tree in device_trees.values(): 506 for device_tree in device_trees.values():
585 device_tree.Display() 507 device_tree.Display()
586 print 508 print
587 509
588 # Display TTY information about devices plugged into hubs. 510 # Display TTY information about devices plugged into hubs.
589 print '==== TTY INFORMATION ====' 511 print '==== TTY INFORMATION ===='
590 for port_map in GetAllPhysicalPortToTTYMaps([plugable_7port], 512 for port_map in GetAllPhysicalPortToTTYMaps([usb_hubs.PLUGABLE_7PORT],
591 device_tree_map=device_trees): 513 device_tree_map=device_trees):
592 print port_map 514 print port_map
593 print 515 print
594 516
595 # Display serial number information about devices plugged into hubs. 517 # Display serial number information about devices plugged into hubs.
596 print '==== SERIAL NUMBER INFORMATION ====' 518 print '==== SERIAL NUMBER INFORMATION ===='
597 for port_map in GetAllPhysicalPortToSerialMaps([plugable_7port], 519 for port_map in GetAllPhysicalPortToSerialMaps([usb_hubs.PLUGABLE_7PORT],
598 device_tree_map=device_trees): 520 device_tree_map=device_trees):
599 print port_map 521 print port_map
522
523 print
524 # Display phone to BattOr map
525 print GenerateSerialMap()
600 print '' 526 print ''
527
601 return 0 528 return 0
602 529
530
531 def ReadSerialMapFile(filename):
532 """Reads JSON file giving phone-to-battor serial number map.
533
534 Parses a JSON file consisting of a list of items of the following form:
535 [{'phone':<phone serial 1>, 'battor':<battor serial 1>},
rnephew (Reviews Here) 2016/03/25 00:17:53 Nit: Spaces here too. See below.
alexandermont 2016/03/28 18:47:29 Done
536 {'phone':<phone serial 2>, 'battor':<battor serial 2>}, ...]
537
538 indicating which phone serial numbers should be matched with
539 which BattOr serial numbers. Returns dictionary of the form:
540
541 {<phone serial 1>: <BattOr serial 1>,
542 <phone serial 2>: <BattOr serial 2>}
543
544 Args:
545 filename: Name of file to read.
546 """
547 result = {}
548 with open(filename, 'r') as infile:
549 in_dict = json.load(infile)
550 for x in in_dict:
551 result[x['phone']] = x['battor']
552 return result
553
554 def GenerateSerialMapFile(filename, hub_types=None):
555 """Writes a map of phone serial numbers to BattOr serial numbers to file.
556
557 Args:
558 filename: Name of file to write.
559 """
560 result = []
561 for (phone, battor) in GenerateSerialMap(hub_types).iteritems():
562 result.append({'phone':phone, 'battor':battor})
rnephew (Reviews Here) 2016/03/25 00:17:53 nit: 'phone': phone, 'battor': battor note the sp
alexandermont 2016/03/28 18:47:29 Done
563 with open(filename, 'w') as outfile:
564 json.dump(result, outfile)
565
566 def GenerateSerialMap(hub_types=None):
567 """Generates a map of phone serial numbers to BattOr serial numbers.
568
569 Generates a JSON file consisting of a list of items of the following form:
570 [{'phone':<phone serial 1>, 'battor':<battor serial 1>},
rnephew (Reviews Here) 2016/03/25 00:17:52 Spaces here too.
alexandermont 2016/03/28 18:47:29 Done
571 {'phone':<phone serial 2>, 'battor':<battor serial 2>}, ...]
572
573 indicating which phone serial numbers should be matched with
574 which BattOr serial numbers. Mapping is based on the physical port numbers
575 of the hubs that the BattOrs and phones are connected to.
576
577 Args:
578 hub_types: List of hub types to check for
579 """
580 hub_types = [usb_hubs.GetHubType(x)
581 for x in hub_types or ['plugable_7port']]
582 devtree = GetBusNumberToDeviceTreeMap(fast=True)
583 battor_serials = list(GetBattorSerialNumbers(devtree))
584 p2serial = GetAllPhysicalPortToSerialMaps(hub_types,
585 device_tree_map=devtree)
586 port_to_devices = collections.defaultdict(list)
587 result = {}
588 for hub in p2serial:
589 for (port, serial) in hub.iteritems():
590 port_to_devices[port].append(serial)
591 for (port, serial_list) in port_to_devices.iteritems():
592 battor_serial = [x for x in serial_list if x in battor_serials]
593 if len(battor_serial) >= 2:
594 raise BattorError('Duplicate BattOr serial numbers detected')
595 if len(battor_serial) == 1:
596 battor_serial = battor_serial[0]
597 phone_serial = [x for x in serial_list if x != battor_serial]
598 if len(phone_serial) >= 2:
599 raise BattorError('Multiple phones matched with same BattOr')
600 if len(phone_serial) == 0:
601 raise BattorError('BattOr has no matching phone')
602 if battor_serial in result:
603 raise BattorError('Duplicate BattOr serial numbers detected')
604 result[phone_serial[0]] = battor_serial
605 return result
606
607 def _PhoneToPathMap(serial, serial_map, devtree):
608 """Maps phone serial number to TTY path, assuming serial map is provided."""
609 battor_serial = serial_map[serial]
610 for tree in devtree.values():
611 for node in tree.AllNodes():
612 if isinstance(node, USBDeviceNode):
613 if node.serial == battor_serial:
614 bus_device_to_tty = GetBusDeviceToTTYMap()
615 bus_device = (node.bus_num, node.device_num)
616 try:
617 return bus_device_to_tty[bus_device]
618 except KeyError:
619 raise BattorError('Device with given serial number not a BattOr '
620 '(does not have TTY path)')
621
622 def _PhoneToPathPorts(serial, hub_types, devtree):
623 """Maps phone serial number to TTY path, assuming hub types are provided."""
624 hub_types = [usb_hubs.GetHubType(x)
625 for x in hub_types or ['plugable_7port']]
626 p2serial = GetAllPhysicalPortToSerialMaps(hub_types,
627 device_tree_map=devtree)
628 p2tty = GetAllPhysicalPortToTTYMaps(hub_types,
629 device_tree_map=devtree)
630
631 # get the port number of this device
632 port_num = -1
633 for hub in p2serial:
634 for (port, s) in hub.iteritems():
635 if serial == s:
636 port_num = port
637 if port_num == -1:
638 raise BattorError('Device with given serial number not found.')
639
640 # get the tty for this port number
641 tty_string = None
642 for hub in p2tty:
643 x = hub.get(port_num)
644 if x is not None:
645 if tty_string:
646 raise BattorError('Two TTY devices with matching port number.')
647 else:
648 tty_string = x
649 return tty_string
650
651 def GetBattorPathFromPhoneSerial(serial, serial_map=None, hub_types=None):
nednguyen 2016/03/25 03:05:29 In which use case a client will not want to use se
rnephew (Reviews Here) 2016/03/25 05:03:19 Thinking more about it, that would most likely hap
nednguyen 2016/03/27 16:44:32 I see. Can we leave the hub_types param out and in
alexandermont 2016/03/28 18:47:29 Done
652 """Gets the TTY path (e.g. '/dev/ttyUSB0') to communicate with the BattOr.
653
654 (1) If serial_map is available, serial_map is treated as a dictionary mapping
655 phone serial numbers to BattOr serial numbers. This function will get the
656 TTY path for the given BattOr serial number.
657
658 (2) If serial_map is None and hub_types is available, hub_types is treated
659 as a list of strings representing the types of hubs that the phones and
660 BattOrs are plugged into (see usb_hubs.py for details). This function will
661 get the BattOr that is connected to the same physical port number,
662 on a different hub, that the phone is connected to.
663
664 (3) If serial_map is None and hub_types is None, then it will assume that the
665 type of hub the BattOrs and phones are plugged into are Plugable USB
666 7-Port Hubs, and then proceed as in (2).
667
668 Args:
669 serial: Serial number of phone connected on the same physical port that
670 the BattOr is connected to.
671 serial_map_file: Map of phone serial numbers to BattOr serial numbers.
672 hub_types: List of hub types to check for. Used only if serial_map_file
673 is None.
674
675 Returns:
676 Device string used to communicate with device.
677
678 Raises:
679 ValueError: If serial number is not given.
680 BattorError: If BattOr not found or unexpected USB topology.
681 """
682 # If there's only one BattOr connected to the system, just use that one.
683 # This allows for use on, e.g., a developer's workstation with no hubs.
684 devtree = GetBusNumberToDeviceTreeMap(fast=True)
685 all_battors = GetBattorList(devtree)
686 if len(all_battors) == 1:
687 return '/dev/' + all_battors[0]
688 if not serial:
689 raise BattorError('Two or more BattOrs connected, no serial provided')
690
691 if serial_map is not None:
692 err_string = 'with given serial number'
693 tty_string = _PhoneToPathMap(serial, serial_map, devtree)
694
rnephew (Reviews Here) 2016/03/25 05:02:41 nit: no space here.
alexandermont 2016/03/28 18:47:29 Done
695 else:
696 err_string = 'on matching port'
697 tty_string = _PhoneToPathPorts(serial, hub_types, devtree)
698 if not tty_string:
rnephew (Reviews Here) 2016/03/25 05:02:41 space here instead.
alexandermont 2016/03/28 18:47:29 Done
699 raise BattorError('No device %s detected.' % err_string)
700 if IsBattor(tty_string, devtree):
701 return '/dev/' + tty_string
702 else:
703 raise BattorError('Device %s is not a BattOr.' % err_string)
704
603 def parse_options(argv): 705 def parse_options(argv):
604 """Parses and checks the command-line options. 706 """Parses and checks the command-line options.
605 707
606 Returns: 708 Returns:
607 A tuple containing the options structure and a list of categories to 709 A tuple containing the options structure and a list of categories to
608 be traced. 710 be traced.
609 """ 711 """
610 USAGE = '''./find_usb_devices [--help] 712 USAGE = '''./find_usb_devices [--help]
611 This script shows the mapping between USB devices and port numbers. 713 This script shows the mapping between USB devices and port numbers.
612 Clients are not intended to call this script from the command line. 714 Clients are not intended to call this script from the command line.
613 Clients are intended to call the functions in this script directly. 715 Clients are intended to call the functions in this script directly.
614 For instance, GetAllPhysicalPortToSerialMaps(...) 716 For instance, GetAllPhysicalPortToSerialMaps(...)
615 Running this script with --help will display this message. 717 Running this script with --help will display this message.
616 Running this script without --help will display information about 718 Running this script without --help will display information about
617 devices attached, TTY mapping, and serial number mapping, 719 devices attached, TTY mapping, and serial number mapping,
618 for testing purposes. See design document for API documentation. 720 for testing purposes. See design document for API documentation.
619 ''' 721 '''
620 parser = argparse.ArgumentParser(usage=USAGE) 722 parser = argparse.ArgumentParser(usage=USAGE)
621 return parser.parse_args(argv[1:]) 723 return parser.parse_args(argv[1:])
622 724
623 def main(): 725 def main():
624 parse_options(sys.argv) 726 parse_options(sys.argv)
625 TestUSBTopologyScript() 727 TestUSBTopologyScript()
626 728
627 if __name__ == "__main__": 729 if __name__ == "__main__":
628 sys.exit(main()) 730 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | devil/devil/utils/find_usb_devices_test.py » ('j') | devil/devil/utils/usb_hubs.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698