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

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 standalone script for update Created 4 years, 8 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=True):
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()
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):
jbudorick 2016/03/30 19:28:58 I should've brought this up on whatever review int
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>},
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 Writes a JSON file consisting of a list of items of the following form:
558 [{'phone': <phone serial 1>, 'battor': <battor serial 1>},
559 {'phone': <phone serial 2>, 'battor': <battor serial 2>}, ...]
560
561 indicating which phone serial numbers should be matched with
562 which BattOr serial numbers. Mapping is based on the physical port numbers
563 of the hubs that the BattOrs and phones are connected to.
564
565 Args:
566 filename: Name of file to write.
567 """
568 result = []
569 for (phone, battor) in GenerateSerialMap(hub_types).iteritems():
570 result.append({'phone': phone, 'battor': battor})
571 with open(filename, 'w') as outfile:
572 json.dump(result, outfile)
573
574 def GenerateSerialMap(hub_types=None):
575 """Generates a map of phone serial numbers to BattOr serial numbers.
576
577 Generates a dict of:
578 {<phone serial 1>: <battor serial 1>,
579 <phone serial 2>: <battor serial 2>}
580 indicating which phone serial numbers should be matched with
581 which BattOr serial numbers. Mapping is based on the physical port numbers
582 of the hubs that the BattOrs and phones are connected to.
583
584 Args:
585 hub_types: List of hub types to check for
jbudorick 2016/03/30 19:28:58 nit: add that this defaults to ['plugable_7port']
alexandermont 2016/03/30 23:35:53 Done
586 """
587 hub_types = [usb_hubs.GetHubType(x)
588 for x in hub_types or ['plugable_7port']]
589 devtree = GetBusNumberToDeviceTreeMap()
590 battor_serials = list(GetBattorSerialNumbers(devtree))
591 p2serial = GetAllPhysicalPortToSerialMaps(hub_types,
jbudorick 2016/03/30 19:28:58 nit: rename p2serial
alexandermont 2016/03/30 23:35:52 Done
592 device_tree_map=devtree)
593 port_to_devices = collections.defaultdict(list)
jbudorick 2016/03/30 19:28:57 Rather than a list of serials, wdyt about having t
alexandermont 2016/03/30 23:35:52 See below.
594 result = {}
595 for hub in p2serial:
596 for (port, serial) in hub.iteritems():
597 port_to_devices[port].append(serial)
jbudorick 2016/03/30 19:28:58 Following from the above, you'd then check whether
alexandermont 2016/03/30 23:35:53 This won't work if the value in the dictionary is
598 for (port, serial_list) in port_to_devices.iteritems():
599 battor_serial = [x for x in serial_list if x in battor_serials]
600 if len(battor_serial) >= 2:
601 raise BattorError('Duplicate BattOr serial numbers detected')
602 if len(battor_serial) == 1:
603 battor_serial = battor_serial[0]
604 phone_serial = [x for x in serial_list if x != battor_serial]
605 if len(phone_serial) >= 2:
606 raise BattorError('Multiple phones matched with same BattOr')
607 if len(phone_serial) == 0:
608 raise BattorError('BattOr has no matching phone')
609 if battor_serial in result:
610 raise BattorError('Duplicate BattOr serial numbers detected')
611 result[phone_serial[0]] = battor_serial
612 return result
613
614 def _PhoneToPathMap(serial, serial_map, devtree):
615 """Maps phone serial number to TTY path, assuming serial map is provided."""
616 battor_serial = serial_map[serial]
617 for tree in devtree.values():
618 for node in tree.AllNodes():
619 if isinstance(node, USBDeviceNode):
620 if node.serial == battor_serial:
621 bus_device_to_tty = GetBusDeviceToTTYMap()
622 bus_device = (node.bus_num, node.device_num)
623 try:
624 return bus_device_to_tty[bus_device]
625 except KeyError:
626 raise BattorError('Device with given serial number not a BattOr '
627 '(does not have TTY path)')
628
629
630 def GetBattorPathFromPhoneSerial(serial, serial_map=None):
631 """Gets the TTY path (e.g. '/dev/ttyUSB0') to communicate with the BattOr.
632
633 (1) If serial_map is a dict, serial_map is treated as a dictionary mapping
jbudorick 2016/03/30 19:28:57 Why is this handling two arguments in one...? Hand
alexandermont 2016/03/30 23:35:52 Done
634 phone serial numbers to BattOr serial numbers. This function will get the
635 TTY path for the given BattOr serial number.
636
637 (2) If serial_map is a string, serial_map is treated as the name of a
638 phone-to-BattOr mapping file (generated with GenerateSerialMapFile)
639 and this will be loaded and used as the dict to map port numbers to
640 BattOr serial numbers.
641
642 Args:
643 serial: Serial number of phone connected on the same physical port that
644 the BattOr is connected to.
645 serial_map_file: Map of phone serial numbers to BattOr serial numbers.
646 hub_types: List of hub types to check for. Used only if serial_map_file
647 is None.
648
649 Returns:
650 Device string used to communicate with device.
651
652 Raises:
653 ValueError: If serial number is not given.
654 BattorError: If BattOr not found or unexpected USB topology.
655 """
656 # If there's only one BattOr connected to the system, just use that one.
657 # This allows for use on, e.g., a developer's workstation with no hubs.
658 devtree = GetBusNumberToDeviceTreeMap()
659 all_battors = GetBattorList(devtree)
660 if len(all_battors) == 1:
661 return '/dev/' + all_battors[0]
662
663 if isinstance(serial_map, str):
664 serial_map = ReadSerialMapFile(serial_map)
665
666 if not isinstance(serial_map, dict):
667 raise ValueError('Incorrect data type for serial_map')
668
669 if not serial:
670 raise BattorError('Two or more BattOrs connected, no serial provided')
671
672 tty_string = _PhoneToPathMap(serial, serial_map, devtree)
673
674 if not tty_string:
675 raise BattorError('No device with given serial number detected.')
676
677 if IsBattor(tty_string, devtree):
678 return '/dev/' + tty_string
679 else:
680 raise BattorError('Device with given serial number is not a BattOr.')
681
603 def parse_options(argv): 682 def parse_options(argv):
604 """Parses and checks the command-line options. 683 """Parses and checks the command-line options.
605 684
606 Returns: 685 Returns:
607 A tuple containing the options structure and a list of categories to 686 A tuple containing the options structure and a list of categories to
608 be traced. 687 be traced.
609 """ 688 """
610 USAGE = '''./find_usb_devices [--help] 689 USAGE = '''./find_usb_devices [--help]
611 This script shows the mapping between USB devices and port numbers. 690 This script shows the mapping between USB devices and port numbers.
612 Clients are not intended to call this script from the command line. 691 Clients are not intended to call this script from the command line.
613 Clients are intended to call the functions in this script directly. 692 Clients are intended to call the functions in this script directly.
614 For instance, GetAllPhysicalPortToSerialMaps(...) 693 For instance, GetAllPhysicalPortToSerialMaps(...)
615 Running this script with --help will display this message. 694 Running this script with --help will display this message.
616 Running this script without --help will display information about 695 Running this script without --help will display information about
617 devices attached, TTY mapping, and serial number mapping, 696 devices attached, TTY mapping, and serial number mapping,
618 for testing purposes. See design document for API documentation. 697 for testing purposes. See design document for API documentation.
619 ''' 698 '''
620 parser = argparse.ArgumentParser(usage=USAGE) 699 parser = argparse.ArgumentParser(usage=USAGE)
621 return parser.parse_args(argv[1:]) 700 return parser.parse_args(argv[1:])
622 701
623 def main(): 702 def main():
624 parse_options(sys.argv) 703 parse_options(sys.argv)
625 TestUSBTopologyScript() 704 TestUSBTopologyScript()
626 705
627 if __name__ == "__main__": 706 if __name__ == "__main__":
628 sys.exit(main()) 707 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | devil/devil/utils/find_usb_devices_test.py » ('j') | devil/devil/utils/testdata/test_serial_map.json » ('J')

Powered by Google App Engine
This is Rietveld 408576698