You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
webserial return wrong data but other methods works fine #151
I'm trying to use webserial to connect android phone with Qualcomm chips. It's EDL mode is a serial port with 0x9008 product ID.
the port is supposed to send 48 bytes data at first time. When i communicate it with python or sudo minicom --device /dev/ttyUSB0. i always have 48 bytes data.
however when i use code snippet below on chrom console. sometimes it return 103 bytes wrong data. And if i tried on another computer everything works fine.
I'm not sure if i provide enough information, if anything i can provide, please feel free to ask.
const f = { usbVendorId: 0x05c6, usbProductId: 0x9008 };
a = await navigator.serial.requestPort({filters: [f]})
await a.open({baudRate: 115200});
b = a.readable.getReader()
r = await b.read();
r["value"]
changed the title [-]webusb return wrong data but other method works fine[/-][+]webserial return wrong data but other methods works fine[/+]on Dec 1, 2021
What is the structure of the 103 bytes of data returned? Is it the expected 48 bytes followed by garbage? Is it two or more 48 byte chunks concatenated together?
When getReader() is called the browser starts reading from the port and adding any data that is received to the stream. When read() is called any data received so far is returned. In general, rather than calling read() and expecting it to contain exactly the data it is looking for a program should call read() until it gets all the data it expects, process that, and then continue reading until it gets the next expected piece of data.
when 103 bytes returned, it's totally wrong data. the first 48 bytes of the 103 bytes are different than the correct data. even rebooting the PC doesn't work
Here is the detail
if i run javascript in crhome console with the computer which works fine
const f = { usbVendorId: 0x05c6, usbProductId: 0x9008 };
a = await navigator.serial.requestPort({filters: [f]})
await a.open({baudRate: 115200});
b = a.readable.getReader()
r = await b.read();
r["value"]
If this is only happening on some Linux systems try disabling the "ModemManager" service. This service is known to try to open and communicate with serial devices and cause problems.
If this is only happening on some Linux systems try disabling the "ModemManager" service. This service is known to try to open and communicate with serial devices and cause problems.
and it cannot explain why minicom works fine, because it also works on serial port.
However i tried another thing. i disable serial driver on the problem PC, so webusb can claim on my original USB interface. and i found it also works fine
What is the structure of the 103 bytes of data returned? Is it the expected 48 bytes followed by garbage? Is it two or more 48 byte chunks concatenated together?
When getReader() is called the browser starts reading from the port and adding any data that is received to the stream. When read() is called any data received so far is returned. In general, rather than calling read() and expecting it to contain exactly the data it is looking for a program should call read() until it gets all the data it expects, process that, and then continue reading until it gets the next expected piece of data.
for normal real serial port it may be true. However for virtual serial port from USB. i don't think there should be garbege.
I'd like to try to reproduce this myself but haven't had time. Something else I'd look at to see if anything is unexpectedly communicating with the device before Chrome opens it is to collect a USB packet trace with Wireshark. You can then line up the USB packets with the data returned by the Web Serial API. That could at least show whether or not something is being corrupted within Chrome.
Here is the info i captured from wireshark. which indeed provide some information. wireshark.zip
in good.pcapng
with filter usb.dst == host and usb.transfer_type == 3. ignore the first 4 packet, that's android fastboot protocol. i use fastboot command to enter into serial mode of my phone.
you can see i do have correct packet here, and in browser, i also have good data.
it seems that my PC automatically send back something to my phone, so my phone response with the redandunt packet. I'm not sure who did it. (but i strongly suspect it's web serial who did it, because the phone serial mode is used for flashing roms, and we have been using it for years)
Even though, web serial should be able to read the all data and return it to me. but web serial only return me the last 103 bytes to me. why? the first 9 bytes are discarded. totally there are 112 bytes (48 bytes good data, the 4 * 16 bytes redandunt data)
There's no reason why Web Serial would send any data not written to the WritableStream to the device. The behavior you are seeing is consistent with another application opening the TTY device, sending some data, reading 9 bytes and then closing it. When Chrome the opens the device it reads the remaining 39 bytes originally sent by the device plus the 80 bytes sent in response to the data written by the other program.
You can see from the auditd log in your previous comment that systemd-udevd also opened /dev/ttyUSB5 before Chrome did.
My guess is that when you disable the serial driver in order to WebUSB instead it means that the /dev/ttyUSB5 device doesn't get created and so whatever is opening it doesn't get a chance to.
Something you can test is performing a Wireshark capture when Chrome isn't running to see if this communication still happens.
My guess is that when you disable the serial driver in order to WebUSB instead it means that the /dev/ttyUSB5 device doesn't get created and so whatever is opening it doesn't get a chance to.
Something you can test is performing a Wireshark capture when Chrome isn't running to see if this communication still happens.
Basically, i have 2 proofs point to chrome:
other serial tools like minicom doesn't have this problem, like i mentioned above. So i've already done the test you said.
maybe you can notice that, in bad.pcapng, the timestamp of packet 1827 and 1833 is really close to each other. That's consistent to what i see, "if i don't call webserial, wireshark shows no one is reading from the serial. And as soon as i call it, it return wrong data."
If it's really something who read the first 9 bytes, it's really strange that it always read just after i call webserial API.
you can see, the serial port is already there after i type "fastboot oem edl" command. this tells my phone to enter into serial mode. (10 seconds of the video)
wireshark shows 4 packet, and there are all fastboot packet, has nothing to do with serial.
before i call webserial API, wireshark shows nothing. if someone else is reading it, the wireshark should show it.
after i wait sometime, i call webserial, the it immediately shows good data and wrong data all together. and the data returned by webserial is wrong. (25 seconds of the video)
I've been reading through qcserial.c to see if there's anything interesting about this USB serial driver. I wonder if it uses some kind of in-band signaling for doing things like setting baud rate and so the system calls Chrome is making to configure the port on connect are causing this data to be sent. Are you using the stock Qualcomm serial driver that comes with that version of Ubuntu?
lsusb
Bus 002 Device 002: ID 8087:8000 Intel Corp.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
**Bus 001 Device 005: ID 05c6:9008 Qualcomm, Inc. Gobi Wireless Modem (QDL mode)**
Bus 001 Device 004: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 003: ID 0451:8044 Texas Instruments, Inc.
Bus 001 Device 002: ID 8087:8008 Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
while i cannot get the correct data. I tried another way: just reset the device state machine by sending a reset command to it.
However it also has problem, when i reset, the ttyUSB re-emulate a new device, which cause webserial crash and report Uncaught (in promise) DOMException: The device has been lost.
Now we really run out of ways. So we just tell our users to set a udev rule, run a script to detach qcserial driver every time they plug the device in
Similar to Linux, you can manually replace the Qualcomm serial driver with the WinUSB driver so that Chrome can get low-level access to the USB device. The tool for that on Windows is called Zadig. This may not be necessary however and I would check first to see whether you observe the same problem you encountered on Linux when using Windows.
Per "#166".
It seems that windows can receive from webserial correctly.
So far, we tell our users to modify /etc/udev/rules.d to remove qcserial driver.
But i think it's really odd to let user modify a so low-level program to use a web app.
We found on mac, WebUSB can work directly. Maybe there is no qcserial driver on it.
BTW. This issue is a little bit similar with #166 .
To be more clear, let me explain the protocol when this issue happen.
once the device boot, it sends hello packet, which is "Uint8Array(48) [1, 0, 0, 0, 48, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", first 4 bytes means "id", hence "hello packet", second 4 bytes is packet length]
Then i need to response something, and if my response is wrong, then the device sends me 'end packet' "Uint8Array(16) [4, 0, 0, 0, 16, 0, 0, 0, 13, 0, 0, 0, 1, 0, 0, 0]". also, first 4 bytes means "end".
when i encouter issue in #166 , the device also sends me "end packet". Which means the device thinks i finish the communication and my response is wrong.
Also , in this issue, the device thinks i send something wrong. Though i didn't send anything. Just read from the device.
We decide to download chronium and build ourselves to check where is the problem.
But we're not familiar with chronium codes and C++.
Would mind giving us some hints? for example which file or which function should we check first?
Activity
[-]webusb return wrong data but other method works fine[/-][+]webserial return wrong data but other methods works fine[/+]reillyeon commentedon Dec 1, 2021
What is the structure of the 103 bytes of data returned? Is it the expected 48 bytes followed by garbage? Is it two or more 48 byte chunks concatenated together?
When
getReader()is called the browser starts reading from the port and adding any data that is received to the stream. Whenread()is called any data received so far is returned. In general, rather than callingread()and expecting it to contain exactly the data it is looking for a program should callread()until it gets all the data it expects, process that, and then continue reading until it gets the next expected piece of data.demonguy commentedon Dec 2, 2021
when 103 bytes returned, it's totally wrong data. the first 48 bytes of the 103 bytes are different than the correct data. even rebooting the PC doesn't work
Here is the detail
if i run javascript in crhome console with the computer which works fine
the result is
However on the problem computer, there is 90% of time i will get data like this
the result is
if i run
minicom --device /dev/ttyUSB0 -b 115200 -Hon the problem PCthe result is good
reillyeon commentedon Dec 2, 2021
If this is only happening on some Linux systems try disabling the "ModemManager" service. This service is known to try to open and communicate with serial devices and cause problems.
demonguy commentedon Dec 2, 2021
it doesn't work even i run
and it cannot explain why minicom works fine, because it also works on serial port.
However i tried another thing. i disable serial driver on the problem PC, so webusb can claim on my original USB interface. and i found it also works fine
reillyeon commentedon Dec 2, 2021
What are the differences between the working PC and the problem PC? Processor type, kernel version, Linux distribution, etc.
demonguy commentedon Dec 2, 2021
nearly same. it's our company Dell PC for business. the only difference is the problem PC is newer.
And both of them are installed ubuntu 20.04 with linux 5.11.0-40 and latest chrome. Details are listed below
Good PC:
Manufacturer: Dell Inc.
Product Name: OptiPlex 9020
CPU: Intel i7-4790
Ubuntu: 20.04.3
Linux: 5.11.0-40-generic
Chrome: Version 96.0.4664.45 (Official Build) (64-bit)
Bad PC:
Manufacturer: Dell Inc.
Product Name: OptiPlex 7080
CPU: Inteli7-10700
Ubuntu: 20.04.2
Linux: 5.11.0-41-generic
Chrome: Version Version 96.0.4664.45 (Official Build) (64-bit)
I also tried another pc which has exactly same hardware and software. also works fine. it feels like one of userspace program problem or bug.
demonguy commentedon Dec 4, 2021
Is there any further debug or experiment i can do? i run out of my methods
demonguy commentedon Dec 7, 2021
I use auditd to check if someone else is using /dev/ttyUSB
But it seems that everything is OK
demonguy commentedon Dec 7, 2021
for normal real serial port it may be true. However for virtual serial port from USB. i don't think there should be garbege.
reillyeon commentedon Dec 7, 2021
I'd like to try to reproduce this myself but haven't had time. Something else I'd look at to see if anything is unexpectedly communicating with the device before Chrome opens it is to collect a USB packet trace with Wireshark. You can then line up the USB packets with the data returned by the Web Serial API. That could at least show whether or not something is being corrupted within Chrome.
demonguy commentedon Dec 13, 2021
Here is the info i captured from wireshark. which indeed provide some information.
wireshark.zip
with filter
usb.dst == host and usb.transfer_type == 3. ignore the first 4 packet, that's android fastboot protocol. i use fastboot command to enter into serial mode of my phone.you can see i do have correct packet here, and in browser, i also have good data.
However when problem occurs, use the same filter, we can see there are redundant data.
So , now i have 2 questions here.
reillyeon commentedon Dec 14, 2021
There's no reason why Web Serial would send any data not written to the
WritableStreamto the device. The behavior you are seeing is consistent with another application opening the TTY device, sending some data, reading 9 bytes and then closing it. When Chrome the opens the device it reads the remaining 39 bytes originally sent by the device plus the 80 bytes sent in response to the data written by the other program.You can see from the auditd log in your previous comment that
systemd-udevdalso opened/dev/ttyUSB5before Chrome did.My guess is that when you disable the serial driver in order to WebUSB instead it means that the
/dev/ttyUSB5device doesn't get created and so whatever is opening it doesn't get a chance to.Something you can test is performing a Wireshark capture when Chrome isn't running to see if this communication still happens.
demonguy commentedon Dec 14, 2021
Basically, i have 2 proofs point to chrome:
minicomdoesn't have this problem, like i mentioned above. So i've already done the test you said.1827and1833is really close to each other. That's consistent to what i see, "if i don't call webserial, wireshark shows no one is reading from the serial. And as soon as i call it, it return wrong data."If it's really something who read the first 9 bytes, it's really strange that it always read just after i call webserial API.
demonguy commentedon Dec 14, 2021
I upload a screencast as evidence.
cast.mp4
reillyeon commentedon Dec 14, 2021
That screen capture is interesting because it looks like the full 112 bytes are received by Chrome this time.
demonguy commentedon Dec 14, 2021
emmmm. i didn't notice it. strange. normally chrome cannot receive everything. Let me try again
reillyeon commentedon Dec 14, 2021
I've been reading through
qcserial.cto see if there's anything interesting about this USB serial driver. I wonder if it uses some kind of in-band signaling for doing things like setting baud rate and so the system calls Chrome is making to configure the port on connect are causing this data to be sent. Are you using the stock Qualcomm serial driver that comes with that version of Ubuntu?demonguy commentedon Dec 14, 2021
I didn't install any qualcomm driver manually. It should come with my ubuntu distribution.
demonguy commentedon Dec 14, 2021
This time, the crhome receive wrong data.
cast.mp4
demonguy commentedon Feb 7, 2022
Is this issue solved?
while i cannot get the correct data. I tried another way: just reset the device state machine by sending a
resetcommand to it.However it also has problem, when i reset, the ttyUSB re-emulate a new device, which cause webserial crash and report
Uncaught (in promise) DOMException: The device has been lost.Now we really run out of ways. So we just tell our users to set a udev rule, run a script to detach qcserial driver every time they plug the device in
reillyeon commentedon Feb 7, 2022
That's the best workaround I have for now as I haven't had time to dive into what is going on with this particular device and driver combination.
demonguy commentedon Feb 8, 2022
Well. Understood. Thanks for you help :)
Please let me know if we can do any experiment or provide any information
demonguy commentedon Apr 22, 2022
Despite we can take advantage of udev on ubuntu
How can we use webUSB on windows for a usb-serial device?
It shows "access denied
reillyeon commentedon Apr 23, 2022
Similar to Linux, you can manually replace the Qualcomm serial driver with the WinUSB driver so that Chrome can get low-level access to the USB device. The tool for that on Windows is called Zadig. This may not be necessary however and I would check first to see whether you observe the same problem you encountered on Linux when using Windows.
demonguy commentedon Apr 23, 2022
I'will take a look at windows and make sure. Then feedback ASAP.
demonguy commentedon Jul 12, 2022
Per "#166".
It seems that windows can receive from webserial correctly.
So far, we tell our users to modify /etc/udev/rules.d to remove qcserial driver.
But i think it's really odd to let user modify a so low-level program to use a web app.
We found on mac, WebUSB can work directly. Maybe there is no qcserial driver on it.
demonguy commentedon Jul 12, 2022
BTW. This issue is a little bit similar with #166 .
To be more clear, let me explain the protocol when this issue happen.
when i encouter issue in #166 , the device also sends me "end packet". Which means the device thinks i finish the communication and my response is wrong.
Also , in this issue, the device thinks i send something wrong. Though i didn't send anything. Just read from the device.
So the problem above is
demonguy commentedon Jul 13, 2022
We decide to download chronium and build ourselves to check where is the problem.
But we're not familiar with chronium codes and C++.
Would mind giving us some hints? for example which file or which function should we check first?
reillyeon commentedon Jul 13, 2022
The data read path for Linux and macOS is implemented in serial_port_underlying_source.cc (in the renderer), serial_port_impl.cc and serial_io_handler_posix.cc. The data write path is the same but starts with serial_port_underlying_sink.cc (in the renderer). Windows is the same but ends with serial_io_handler_win.cc