Porównaj commity

...

3 Commity

Autor SHA1 Wiadomość Data
felixdoerre c71c9bac5d
Merge 7a900fe51e into d11ca092f7 2024-04-19 19:00:53 +02:00
Angus Gratton d11ca092f7 shared/tinyusb: Fix dynamic USB control callbacks for wLength==0.
In the case where an OUT control transfer triggers with wLength==0 (i.e.
all data sent in the SETUP phase, and no additional data phase) the
callbacks were previously implemented to return b"" (i.e. an empty buffer
for the data phase).

However this didn't actually work as intended because b"" can't provide a
RW buffer (needed for OUT transfers with a data phase to write data into),
so actually the endpoint would stall.

The symptom was often that the device process the request (if processing
it in the SETUP phase when all information was already available), but the
host sees the endpoint stall and eventually returns an error.

This commit changes the behaviour so returning True from the SETUP phase of
a control transfer queues a zero length status response.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-04-17 12:39:47 +10:00
Felix Dörre 7a900fe51e docs: Update docs to replace ifconfig with ipconfig.
Signed-off-by: Felix Dörre <felix@dogcraft.de>
2024-03-20 22:08:59 +00:00
10 zmienionych plików z 93 dodań i 37 usunięć

Wyświetl plik

@ -80,7 +80,7 @@ The :mod:`network` module::
wlan.isconnected() # check if the station is connected to an AP
wlan.connect('ssid', 'key') # connect to an AP
wlan.config('mac') # get the interface's MAC address
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
wlan.ipconfig('addr4') # get the interface's IPv4 addresses
ap = network.WLAN(network.AP_IF) # create access-point interface
ap.config(ssid='ESP-AP') # set the SSID of the access point
@ -98,7 +98,7 @@ A useful function for connecting to your local WiFi network is::
wlan.connect('ssid', 'key')
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
print('network config:', wlan.ipconfig('addr4'))
Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual, and the ``requests`` module for
@ -121,7 +121,7 @@ To use the wired interfaces one has to specify the pins and mode ::
lan = network.LAN(mdc=PIN_MDC, ...) # Set the pin and mode configuration
lan.active(True) # activate the interface
lan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
lan.ipconfig('addr4') # get the interface's IPv4 addresses
The keyword arguments for the constructor defining the PHY type and interface are:

Wyświetl plik

@ -59,7 +59,7 @@ The :mod:`network` module::
wlan.isconnected() # check if the station is connected to an AP
wlan.connect('ssid', 'key') # connect to an AP
wlan.config('mac') # get the interface's MAC address
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
wlan.ipconfig('addr4') # get the interface's IPv4 addresses
ap = network.WLAN(network.AP_IF) # create access-point interface
ap.active(True) # activate the interface
@ -76,7 +76,7 @@ A useful function for connecting to your local WiFi network is::
wlan.connect('ssid', 'key')
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
print('network config:', wlan.ipconfig('addr4'))
Once the network is established the :mod:`socket <socket>` module can be used
to create and use TCP/UDP sockets as usual.

Wyświetl plik

@ -19,10 +19,10 @@ You can check if the interfaces are active by::
You can also check the network settings of the interface by::
>>> ap_if.ifconfig()
('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8')
>>> ap_if.ipconfig('addr4')
('192.168.4.1', '255.255.255.0')
The returned values are: IP address, netmask, gateway, DNS.
The returned values are: IP address and netmask.
Configuration of the WiFi
-------------------------
@ -45,8 +45,8 @@ To check if the connection is established use::
Once established you can check the IP address::
>>> sta_if.ifconfig()
('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8')
>>> sta_if.ipconfig('addr4')
('192.168.0.2', '255.255.255.0')
You can then disable the access-point interface if you no longer need it::
@ -64,7 +64,7 @@ connect to your WiFi network::
sta_if.connect('<ssid>', '<key>')
while not sta_if.isconnected():
pass
print('network config:', sta_if.ifconfig())
print('network config:', sta_if.ipconfig('addr4'))
Sockets
-------

Wyświetl plik

@ -130,15 +130,25 @@ Methods
Second argument is a memoryview to read the USB control request
data for this stage. The memoryview is only valid until the
callback function returns.
callback function returns. Data in this memoryview will be the same
across each of the three stages of a single transfer.
A successful transfer consists of this callback being called in sequence
for the three stages. Generally speaking, if a device wants to do
something in response to a control request then it's best to wait until
the ACK stage to confirm the host controller completed the transfer as
expected.
The callback should return one of the following values:
- ``False`` to stall the endpoint and reject the transfer.
- ``False`` to stall the endpoint and reject the transfer. It won't
proceed to any remaining stages.
- ``True`` to continue the transfer to the next stage.
- A buffer object to provide data for this stage of the transfer.
This should be a writable buffer for an ``OUT`` direction transfer, or a
readable buffer with data for an ``IN`` direction transfer.
- A buffer object can be returned at the SETUP stage when the transfer
will send or receive additional data. Typically this is the case when
the ``wLength`` field in the request has a non-zero value. This should
be a writable buffer for an ``OUT`` direction transfer, or a readable
buffer with data for an ``IN`` direction transfer.
- ``xfer_cb`` - This callback is called whenever a non-control
transfer submitted by calling :func:`USBDevice.submit_xfer` completes.

Wyświetl plik

@ -10,7 +10,7 @@ Example usage::
import network
nic = network.LAN(0)
print(nic.ifconfig())
print(nic.ifconfig("addr4"))
# now use socket as usual
...

Wyświetl plik

@ -13,7 +13,7 @@ Example usage::
import network
nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4)
print(nic.ifconfig())
print(nic.ipconfig("addr4"))
# now use socket as usual
...
@ -56,16 +56,6 @@ Methods
Returns ``True`` if the physical Ethernet link is connected and up.
Returns ``False`` otherwise.
.. method:: WIZNET5K.ifconfig([(ip, subnet, gateway, dns)])
Get/set IP address, subnet mask, gateway and DNS.
When called with no arguments, this method returns a 4-tuple with the above information.
To set the above values, pass a 4-tuple with the required information. For example::
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: WIZNET5K.regs()
Dump the WIZnet5x00 registers. Useful for debugging.

Wyświetl plik

@ -24,7 +24,7 @@ For example::
print("Waiting for connection...")
while not nic.isconnected():
time.sleep(1)
print(nic.ifconfig())
print(nic.ipconfig("addr4"))
# now use socket as usual
import socket
@ -113,8 +113,46 @@ parameter should be `id`.
connected to the AP. The list contains tuples of the form
(MAC, RSSI).
.. method:: AbstractNIC.ipconfig('param')
AbstractNIC.ipconfig(param=value, ...)
Get or set interface-specific ip-configuration interface parameters.
Supported parameters are (availability subject to compile-time flags):
* ``dhcp4`` (``True/False``) obtain an IPv4 address, gateway and dns
server via DHCP. This method does not block and wait for an address
to be obtained. To check if an address was obtained, use the read-only
property ``has_dhcp4``.
* ``gw4`` Get/set the IPv4 default-gateway.
* ``dhcp6`` (``True/False``) obtain a DNS server via stateless DHCPv6.
Obtaining IP Addresses via DHCPv6 is currently not implemented.
* ``autoconf6`` (``True/False``) obtain a stateless IPv6 address via
the network prefix shared in router advertisements. To check if a
stateless address was obtained, use the read-only
property ``has_autoconf6``.
* ``addr4`` (e.g. ``192.168.0.4/24``) obtain the current IPv4 address
and network mask as ``(ip, subnet)``-tuple, regardless of how this
address was obtained. This method can be used to set a static IPv4
address either as ``(ip, subnet)``-tuple or in CIDR-notation.
* ``addr6`` (e.g. ``fe80::1234:5678``) obtain a list of current IPv6
addresses as ``(ip, state, preferred_lifetime, valid_lifetime)``-tuple.
This include link-local, slaac and static addresses.
``preferred_lifetime`` and ``valid_lifetime`` represent the remaining
valid and preferred lifetime of each IPv6 address, in seconds.
``state`` indicates the current state of the address:
* ``0x08`` - ``0x0f`` indicates the address is tentative, counting the
number of probes sent.
* ``0x10`` The address is deprecated (but still valid)
* ``0x30`` The address is preferred (and valid)
* ``0x40`` The address is duplicated and can not be used.
This method can be used to set a static IPv6
address.
.. method:: AbstractNIC.ifconfig([(ip, subnet, gateway, dns)])
Deprecated, only non-lwip ports.
Get/set IP-level network interface parameters: IP address, subnet mask,
gateway and DNS server. When called with no arguments, this method returns
a 4-tuple with the above information. To set the above values, pass a
@ -195,6 +233,19 @@ The following are functions available in the network module.
The default hostname is typically the name of the board.
.. function:: ipconfig('param')
ipconfig(param=value, ...)
Get or set global ip-configuration parameters.
Supported parameters are (availability subject to compile-time flags):
* ``dns`` Get/set DNS server. This method can support both, IPv4 and
IPv6 addresses.
* ``prefer`` (``4/6``) Specify which address type to return, if a domain
name has both A and AAAA records. Note, that this does not clear the
local DNS cache, so that any previously obtained addresses might not
change.
.. function:: phy_mode([mode])
Get or set the PHY mode.

Wyświetl plik

@ -528,7 +528,7 @@ Ethernet. Example usage::
lan.active(True)
If there is a DHCP server in the LAN, the IP address is supplied by that server.
Otherwise, the IP address can be set with lan.ifconfig(). The default address
Otherwise, the IP address can be set with lan.ipconfig(addr4="..."). The default address
is 192.168.0.1.
Teensy 4.1 does not have an Ethernet jack on the board, but PJRC offers an

Wyświetl plik

@ -469,9 +469,9 @@ An example ``config.py`` might look like:
for ap in wl.scan():
print(ap)
""",], # Print out nearby WiFi networks.
"wl_ifconfig": [
"wl_ipconfig": [
"exec",
"import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ifconfig())",
"import network; sta_if = network.WLAN(network.STA_IF); print(sta_if.ipconfig('addr4'))",
""",], # Print ip address of station interface.
"test": ["mount", ".", "exec", "import test"], # Mount current directory and run test.py.
"demo": ["run", "path/to/demo.py"], # Execute demo.py on the device.

Wyświetl plik

@ -295,6 +295,7 @@ static bool runtime_dev_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_cont
mp_obj_usb_device_t *usbd = MP_OBJ_TO_PTR(MP_STATE_VM(usbd));
tusb_dir_t dir = request->bmRequestType_bit.direction;
mp_buffer_info_t buf_info;
bool result;
if (!usbd) {
return false;
@ -319,7 +320,7 @@ static bool runtime_dev_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_cont
// Check if callback returned any data to submit
if (mp_get_buffer(cb_res, &buf_info, dir == TUSB_DIR_IN ? MP_BUFFER_READ : MP_BUFFER_RW)) {
bool result = tud_control_xfer(USBD_RHPORT,
result = tud_control_xfer(USBD_RHPORT,
request,
buf_info.buf,
buf_info.len);
@ -328,17 +329,21 @@ static bool runtime_dev_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_cont
// Keep buffer object alive until the transfer completes
usbd->xfer_data[0][dir] = cb_res;
}
return result;
} else {
// Expect True or False to stall or continue
result = mp_obj_is_true(cb_res);
if (stage == CONTROL_STAGE_ACK) {
if (stage == CONTROL_STAGE_SETUP && result) {
// If no additional data but callback says to continue transfer then
// queue a status response.
tud_control_status(rhport, request);
} else if (stage == CONTROL_STAGE_ACK) {
// Allow data to be GCed once it's no longer in use
usbd->xfer_data[0][dir] = mp_const_none;
}
return mp_obj_is_true(cb_res);
}
return result;
}
static bool runtime_dev_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {