Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Way to use the libusb #61

Open
BDhackers009 opened this issue Mar 29, 2024 · 10 comments
Open

Way to use the libusb #61

BDhackers009 opened this issue Mar 29, 2024 · 10 comments
Assignees
Labels
enhancement New feature or request question Further information is requested

Comments

@BDhackers009
Copy link

Hello sir, so I just installed anotherterm on my phone. previously I was using Termux. But I wanted to use my phone to flash or program my mcu's like esp32/esp866. I installed libusb following the wiki. But now how should I proceed? I mean how can i get a port to use in tools like esptool. Sorry I'm new to this libusb thing. Any kind of information will help sir. Btw thanks for your effort

@green-green-avk green-green-avk self-assigned this Mar 30, 2024
@green-green-avk green-green-avk added enhancement New feature or request question Further information is requested labels Mar 30, 2024
@green-green-avk green-green-avk added this to To do in Another Term Environment via automation Mar 30, 2024
@green-green-avk
Copy link
Owner

Hmm... So, you need a serial port not the usbcore functionality...
Well, I definitely need to add some serial driver emulation into PRoot for good...

However as long as esptool is a Python script and it uses the serial package:

In your project directory:

mkdir -p 'serial_wrapper'

serial_wrapper/protocol_termsh.py:

from __future__ import absolute_import

#import logging
import numbers

from serial.serialutil import SerialBase, SerialException, to_bytes, iterbytes, SerialTimeoutException, PortNotOpenError

import subprocess
import select, fcntl, termios, sys

class Serial(SerialBase):
    """Serial port implementation that simulates a loop back connection in plain software."""

    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
                 9600, 19200, 38400, 57600, 115200)

    def __init__(self, *args, **kwargs):
        self.proc = None
        self._cancel_write = False
        super(Serial, self).__init__(*args, **kwargs)

    def open(self):
        """\
        Open port with current settings. This may throw a SerialException
        if the port cannot be opened.
        """
        if self.is_open:
            raise SerialException("Port is already open.")

        # not that there is anything to open, but the function applies the
        # options found in the URL
        self.from_url(self.port)

        # not that there anything to configure...
        self._reconfigure_port()
        # all things set up get, now a clean start
        self.is_open = True
        if not self._dsrdtr:
            self._update_dtr_state()
        if not self._rtscts:
            self._update_rts_state()
        self.reset_input_buffer()
        self.reset_output_buffer()

    def close(self):
        if self.is_open:
            self.is_open = False
            proc = self.proc
            if proc is not None:
                proc.terminate()

    def _reconfigure_port(self):
        """\
        Set communication parameters on opened port. For the loop://
        protocol all settings are ignored!
        """
        # not that's it of any real use, but it helps in the unit tests
        if not isinstance(self._baudrate, numbers.Integral) or not 0 < self._baudrate < 2 ** 32:
            raise ValueError("invalid baudrate: {!r}".format(self._baudrate))
        proc = self.proc
        if proc is not None:
            proc.terminate()
        self.proc = subprocess.Popen(('termsh', 'serial', '-i', f'{self._baudrate}'), bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    def from_url(self, url):
        """extract host and port from an URL string"""
        pass

    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

    def __check(self, proc):
        r = proc.poll()
        if r is None:
            return
        raise ConnException(proc.stderr.read().decode())

    @property
    def in_waiting(self):
        """Return the number of bytes currently in the input buffer."""
        if not self.is_open:
            raise PortNotOpenError()
        proc = self.proc
        if proc is None:
            raise PortNotOpenError()
        r = bytearray(4)
        fcntl.ioctl(proc.stdout.fileno(), termios.FIONREAD, r)
        return int.from_bytes(r, sys.byteorder)

    def read(self, size=1):
        """\
        Read size bytes from the serial port. If a timeout is set it may
        return less characters as requested. With no timeout it will block
        until the requested number of bytes is read.
        """
        if not self.is_open:
            raise PortNotOpenError()
        proc = self.proc
        if proc is None:
            raise PortNotOpenError()
        src = proc.stdout
        poll = select.poll()
        try:
            poll.register(src.fileno(), select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP | select.POLLRDHUP)
            if len(poll.poll(self._timeout * 1000)) > 0:
                return src.read(size)
            else:
                return b''
        except BrokenPipeError as e:
            raise SerialException(e)

    def cancel_read(self):
        pass

    def cancel_write(self):
        pass

    def write(self, data):
        """\
        Output the given byte string over the serial port. Can block if the
        connection is blocked. May raise SerialException if the connection is
        closed.
        """
        self._cancel_write = False
        if not self.is_open:
            raise PortNotOpenError()
        proc = self.proc
        if proc is None:
            raise PortNotOpenError()
        self.__check(proc)
        try:
            proc.stdin.write(data)
        except BrokenPipeError as e:
            raise SerialException(e)

    def flush(self):
        if not self.is_open:
            raise PortNotOpenError()
        proc = self.proc
        if proc is None:
            raise PortNotOpenError()
        self.__check(proc)
        try:
            proc.stdin.flush()
        except BrokenPipeError as e:
            raise SerialException(e)

    def reset_input_buffer(self):
        """Clear input buffer, discarding all that is in the buffer."""
        pass

    def reset_output_buffer(self):
        """\
        Clear output buffer, aborting the current output and
        discarding all that is in the buffer.
        """
        pass

    @property
    def out_waiting(self):
        """Return how many bytes the in the outgoing buffer"""
        if not self.is_open:
            raise PortNotOpenError()
        return 0

    def _update_break_state(self):
        """\
        Set break: Controls TXD. When active, to transmitting is
        possible.
        """
        pass

    def _update_rts_state(self):
        """Set terminal status line: Request To Send"""
        pass

    def _update_dtr_state(self):
        """Set terminal status line: Data Terminal Ready"""
        pass

    @property
    def cts(self):
        """Read terminal status line: Clear To Send"""
        if not self.is_open:
            raise PortNotOpenError()
        return self._rts_state

    @property
    def dsr(self):
        """Read terminal status line: Data Set Ready"""
        return self._dtr_state

    @property
    def ri(self):
        """Read terminal status line: Ring Indicator"""
        if not self.is_open:
            raise PortNotOpenError()
        return False

    @property
    def cd(self):
        """Read terminal status line: Carrier Detect"""
        if not self.is_open:
            raise PortNotOpenError()
        return True

Augment esptool with (see https://github.com/espressif/esptool/blob/ef8ee8aedff5a642c0cf8e10997ad1bb373bf0a2/esptool/loader.py#L30):

serial.protocol_handler_packages.append('serial_wrapper')

Now (the only) serial port (USB or Bluetooth) on your system could be referred as termsh://.

Feel free to improve the serial_wrapper/protocol_termsh.py implementation as you wish.
See termsh serial info here.

@BDhackers009
Copy link
Author

BDhackers009 commented Mar 30, 2024

First of all thanks a lot sir you came up with a solution that fast. Secondly I'm not good at programming nor very experienced in *nix.

I did create serial_wrapper/protocol_termsh.py inside esptool/esptool/ directory where the loader.py is and then added

serial.protocol_handler_packages.append('serial_wrapper')

under the import Serial line in line 30. then tried running

esptool.py --chip esp32 --port termsh:///dev/bus/usb/001/002 chip_id

but it threw some errors. Now I wanna know actually how do I use this cool script ☹️. Could you please help me more sir if you got time. I would be eternally grateful.

@green-green-avk
Copy link
Owner

What errors?

@BDhackers009
Copy link
Author

BDhackers009 commented Mar 31, 2024

Here it is...

Screenshot_20240331_131846_Another Term

@green-green-avk
Copy link
Owner

Uh, huh... /dev/tty* for serial ports emulation by PRoot seems desperately required here...

@BDhackers009
Copy link
Author

Uh, huh... /dev/tty* for serial ports emulation by PRoot seems desperately required here...

So this is a dead end?

@green-green-avk
Copy link
Owner

Hmm...

It seems, the serial Python library was made in a sort of stupid way: there is no API to return the whole modem state in an atomic manner...

Of course, it's possible to change UnixTightReset to ClassicReset in the esptool for this particular case (or make a custom serial library with the extended API?) and implement a modem control API by an additional couple of pipes in termsh serial... What type of chip your device has? I need to check if this support is already implemented in the USBSerial.

@BDhackers009
Copy link
Author

Its showing CH340 as the COM port. And its an ESP32. However I do have some other esp32 and esp8266 modules lying around.

image

@BDhackers009
Copy link
Author

I recently found this Github repo. He is using those codes to flash firmware in his mcu boards. It can be helpful for this.

@BDhackers009
Copy link
Author

Sir any update?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
Development

No branches or pull requests

2 participants