connect.py: basic usb connection procedure
[renesas-ra-flasher] / flasher / connect.py
1 # Copyright (C) - Robin Krens - 2024
2
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
17
18 import sys
19 import serial
20 import serial.threaded
21 import time
22 import usb.core
23 import usb.util
24
25 LOW_PULSE = 0x00
26 ACK = 0x00
27 GENERIC_CODE = 0x55
28 BOOT_CODE = 0xC3
29
30 VENDOR_ID = 0x045B
31 PRODUCT_ID = 0x0261
32
33 EP_IN = 0x82
34 EP_OUT = 0x02
35
36 MAX_TRIES = 20
37
38 def find_device(vendor_id, product_id):
39     dev = usb.core.find(idVendor=vendor_id, idProduct=product_id)
40     if dev is None:
41         raise ValueError(f"Device {vendor_id}:{product_id} not found\n Are you sure it is connected?")
42
43     for config in dev:
44         for intf in config:
45             if usb.util.find_descriptor(config, custom_match=lambda d: (d.bInterfaceClass == 0x02 or d.bInterfaceClass == 0xFF)):
46                 print(f"Found serial device with 0x02 | 0xFF")
47                 TxD, RxD = None, None
48                 if dev.is_kernel_driver_active(intf.bInterfaceNumber):
49                     print(f"Found kernel driver, detaching ... ")
50                     dev.detach_kernel_driver(intf.bInterfaceNumber)
51                 for ep in intf:
52                     if (ep.bmAttributes == 0x02):
53                         if ep.bEndpointAddress == EP_IN:
54                             RxD = ep
55                             print(ep)
56                         elif ep.bEndpointAddress == EP_OUT:
57                             TxD = ep
58                             print(ep)
59                 return (dev, RxD, TxD)
60
61     raise ValueError("Device does not have a serial interface")
62
63 def establish_connection():
64     dev, rx_ep, tx_ep = find_device(0x1a86, 0x7523)
65     ret = []
66     for i in range(MAX_TRIES):
67         try:
68             tx_ep.write(b'\x00', 100)
69             ret = rx_ep.read(1, 100)
70             if a[0] == ACK:
71                 print("ACK received")
72                 return True
73         except:
74             print(f"Timeout: retry #", i)
75     return False
76
77 def confirm_connection():
78     dev, rx_ep, tx_ep = find_device(0x1a86, 0x7523)
79     ret = []
80     for i in range(MAX_TRIES):
81         try:
82             tx_ep.write(b'\x55', 100)
83             ret = rx_ep.read(1, 100)
84             if a[0] == BOOT_CODE:
85                 print("ACK received")
86                 return True
87         except:
88             print(f"Timeout: retry #", i)
89     return False
90
91 if not establish_connection():
92     print("Cannot connect")
93     sys.exit(0)
94
95 if not confirm_connection():
96     print("Failed to confirm boot code")
97     sys.exit(0)