Compare commits

..
Author SHA1 Message Date
Leency 658a3bc5dd kernel/net: keep out-of-order TCP segments in their own NET_BUFFs
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 26s
Test PR / Build (en_US) (pull_request) Successful in 3m34s
Test PR / Build (ru_RU) (pull_request) Successful in 3m41s
Test PR / Build (es_ES) (pull_request) Successful in 3m44s
Summary: the reassembly queue no longer copies every out-of-order segment
into a malloc'd node; it queues the NET_BUFF the segment arrived in, as
suggested in review. Also fixes a stuck full queue and FIN processing in
the FIN_WAIT states.

Details:
malloc is the kernel's small heap: 128 KB with no way to grow. One socket
was allowed 64 queued segments, about 94 KB of payload, so a single
download over a lossy link could take almost the whole heap away from
every other kernel user. The buffer the segment arrived in is owned by
nobody else, so it now becomes the queue node itself: NextPtr links the
queue, offset and length are narrowed down to the TCP payload, type is
set to the new NET_BUFF_TCP_REASM, and the sequence number and FIN flag
are kept right behind the NET_BUFF header (TCP_reasm_buff), over link
and IP headers that are no longer needed. Nothing is allocated or copied.

tcp_reassemble takes ownership of the buffer: it either queues or frees
it, and tcp_input marks this with TCP_BIT_BUFF_QUEUED so that its exit
path skips net_buff_free. Queued buffers come from the pool the network
drivers receive into, so besides the per-socket limit of 64 there is a
limit for all sockets together (TCP_reasm_maxbuffs, a quarter of the
pool), counted in TCP_reasm_buffs.

Neither limit applies to a segment that starts at RCV_NXT once the
connection is established. That segment is the one which drains the
queue; with the limit reached it used to be dropped like any other, and
a full queue could then never move again. Before ESTABLISHED nothing is
delivered, so there the limits stay in force.

The queue also records a FIN and tcp_reassemble returns TH_FIN once the
FIN is next in sequence, so tcp_input processes it without touching the
freed segment. This matters beyond out-of-order segments: the in-order
path is only taken in ESTABLISHED, so in FIN_WAIT_1 and FIN_WAIT_2 every
segment, in order or not, goes through the queue. Before, the FIN of a
peer answering our close was never processed there and the connection
never reached TIME_WAIT. Data is not delivered before the connection is
established; tcp_reassemble_drain delivers it once it is.

Tested in QEMU with rtl8139 and a relay that drops and reorders the data
segments of a 2 MB transfer checked byte by byte in the guest.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-28 14:42:02 +03:00
LeencyandClaude Opus 5 134f6c1936 kernel/net: implement the TCP reassembly queue for out-of-order segments
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 38s
Test PR / Build (en_US) (pull_request) Successful in 4m23s
Test PR / Build (es_ES) (pull_request) Successful in 3m54s
Test PR / Build (ru_RU) (pull_request) Successful in 4m18s
Summary: tcp_reassemble was a stub that returned immediately, so every
segment arriving out of order was discarded and a single lost packet threw
away the whole window in flight behind it.

Подробно:
The receive path had two exits: data landing exactly at RCV_NXT was copied
into the socket buffer, and anything else fell into .out_of_order, which
called the empty tcp_reassemble and jumped to .final_processing with a
comment reading "HACK because of unimplemented reassembly queue". The peer
then had to retransmit not only the lost segment but every segment sent
after it, and the connection collapsed to stop-and-wait for the duration of
the recovery. On a lossy link this is the difference between a download
running at line rate and one crawling.

The queue is a singly linked list of tcp_reasm_seg nodes hanging off
TCP_SOCKET.seg_next, sorted by sequence number, with the segment payload
copied into the node so that the caller can free the packet buffer as usual.
tcp_reassemble inserts and then delivers; tcp_reassemble_drain only delivers
and is used where a connection reaches ESTABLISHED. Delivery walks the list
from the head, trimming each node against RCV_NXT and stopping at the first
hole, so overlapping retransmissions never deliver a byte twice. If
socket_ring_write cannot take everything -- the application is not reading
fast enough -- RCV_NXT advances only by what was actually stored and the
remainder stays queued, keeping the advertised window honest.

All sequence arithmetic subtracts and tests the sign, so it is correct
across the 32-bit wraparound. Segments below RCV_NXT are trimmed, complete
duplicates and data more than a receive buffer ahead of RCV_NXT are dropped,
and the queue is bounded at TCP_reasm_maxsegs nodes per socket by a counter
in the socket structure -- counting only the nodes walked during insertion
would bound nothing, since segments arriving in descending sequence order
insert at the head every time. socket_free releases anything still queued.

Two callers in tcp_input already tested seg_next before taking their fast
paths, so both the header-prediction path and the in-order slow path now
correctly divert into the queue while it is non-empty, and the retransmission
that closes a hole drains everything contiguous behind it in one go. A FIN
riding on an out-of-order segment is deliberately left unprocessed; the peer
retransmits it and it is handled when it arrives in sequence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 13:32:06 +03:00
635 changed files with 282591 additions and 71842 deletions

No files matched your search

-54
View File
@@ -1,54 +0,0 @@
# =============================================================================
# Apps
# User-facing applications, games, multimedia, UI and desktop resources
# =============================================================================
^programs/(cmm|demos|emulator|games|media|other)/.* @KolibriOS/apps
^contrib/(games|media|other)/.* @KolibriOS/apps
^skins/.* @KolibriOS/apps
# =============================================================================
# System
# Kernel, drivers, filesystems, SDK, libraries, toolchain and system utilities
# =============================================================================
^kernel/.* @KolibriOS/system
^drivers/.* @KolibriOS/system
^programs/(bcc32|develop|fs|hd_load|system|testing)/.* @KolibriOS/system
^contrib/(C_Layer|sdk|toolchain)/.* @KolibriOS/system
# Shared system/API includes in programs/
^programs/[^/]+\\.inc$ @KolibriOS/system
# =============================================================================
# Network
# Network stack, network drivers, protocols, libraries and network applications
# =============================================================================
^kernel/trunk/network/.* @KolibriOS/network
^drivers/ethernet/.* @KolibriOS/network
^drivers/(mii|netdrv)\\.inc$ @KolibriOS/network
^programs/network/.* @KolibriOS/network
^programs/network\\.inc$ @KolibriOS/network
^programs/develop/libraries/(http|network|kos_mbedtls)/.* @KolibriOS/network
^contrib/network/.* @KolibriOS/network
# =============================================================================
# DevOps
# CI/CD, repository infrastructure, build system and autobuild configuration
# =============================================================================
^\\.gitea/.* @KolibriOS/devops
^_tools/.* @KolibriOS/devops
^\\.gitmodules$ @KolibriOS/devops
^build\\.txt$ @KolibriOS/devops
^tup\\.config\\.template$ @KolibriOS/devops
-35
View File
@@ -19,38 +19,3 @@
owner: "{{ storage_user }}"
group: "{{ storage_user }}"
mode: preserve
# per-program binaries browsable at <version>/<lang>/data/, like on the old builds server
- name: Creating build tree folders
ansible.builtin.file:
path: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
state: directory
owner: "{{ storage_user }}"
group: "{{ storage_user }}"
mode: '0755'
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
- name: Unpacking build trees
ansible.builtin.unarchive:
src: "{{ item }}"
dest: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
owner: "{{ storage_user }}"
group: "{{ storage_user }}"
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
# stable URL for the newest build: <storage_path>/latest/<lang>/...
- name: Updating latest symlink
ansible.builtin.file:
src: "{{ version }}"
dest: "{{ storage_path }}/latest"
state: link
force: true
owner: "{{ storage_user }}"
group: "{{ storage_user }}"
# emulators hardcode <site root>/<lang>/data/data/kolibri.img; storage_path is the ci folder, one level under the site root
- name: Sending bare images to stable emulator paths
ansible.builtin.copy:
src: "{{ stable_artifact_path }}/"
dest: "{{ storage_path }}/../"
mode: preserve
+23 -84
View File
@@ -62,7 +62,7 @@ jobs:
make -f Makefile.lin32
chmod +x c--
mv c-- /home/autobuild/tools/win32/bin/c--
cp ${{ gitea.workspace }}/programs/develop/cmm/c--.ini /home/autobuild/tools/win32/bin/c--.ini
cp ${{ gitea.workspace }}/programs/cmm/c--/c--.ini /home/autobuild/tools/win32/bin/c--.ini
make -f Makefile.lin32 clean
- name: Install TCC
@@ -162,13 +162,12 @@ jobs:
tup init
tup variant ${{ matrix.lang }}.config
# build the image for language variant; keep the tup log for publishing
# build the image for language variant
- name: Build KolibriOS
run: |
set -o pipefail
export PATH=/home/autobuild/tools/win32/bin:$PATH
source kos32-export-env-vars ${{ gitea.workspace }}
tup build-${{ matrix.lang }} 2>&1 | tee build.log
tup build-${{ matrix.lang }}
# stamp the cache with its commit so later builds diff against it
- name: Record cache base commit
@@ -182,26 +181,15 @@ jobs:
id: vars
run: echo "descr=$(git describe --tags)" >> $GITEA_OUTPUT
# stage build outputs under their final names, plus distribution kit and checksums
- name: Prepare artifacts
# rename build outputs to their final names so artifacts are bare files
- name: Rename images
run: |
set -e
BASE="kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}"
for ext in img iso raw; do
cp "build-${{ matrix.lang }}/data/kolibri.$ext" "$BASE.$ext"
cp "build-${{ matrix.lang }}/data/kolibri.$ext" \
"kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.$ext"
done
# zip: distr targets Windows/DOS users, Explorer opens it natively
(cd "build-${{ matrix.lang }}/data" && zip -r -9 -q "${{ gitea.workspace }}/$BASE.distr.zip" distribution_kit)
# whole build tree for per-program downloads; the big images ship separately
tar -C "build-${{ matrix.lang }}" \
--exclude './data/kolibri.iso' \
--exclude './data/kolibri.raw' \
--exclude './data/distribution_kit' \
-czf "$BASE.tree.tar.gz" .
sha256sum "$BASE".img "$BASE".iso "$BASE".raw "$BASE".distr.zip > "$BASE.sha256sums.txt"
mv build.log "$BASE.build.log"
# publish the images; longer retention for the floppy image
#publish the three images; longer retention for the floppy image.
- name: Upload floppy image
uses: actions/upload-artifact@v3
with:
@@ -223,34 +211,6 @@ jobs:
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.raw
retention-days: 15
- name: Upload distribution kit
uses: actions/upload-artifact@v3
with:
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
retention-days: 30
- name: Upload checksums
uses: actions/upload-artifact@v3
with:
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
retention-days: 90
- name: Upload build log
uses: actions/upload-artifact@v3
with:
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
retention-days: 90
- name: Upload build tree
uses: actions/upload-artifact@v3
with:
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
retention-days: 15
deploy:
name: "Publish Images"
runs-on: ubuntu-latest
@@ -275,50 +235,31 @@ jobs:
run: |
set -eu
rm -rf ./norm-artifacts ./stable-artifacts ./tree-artifacts
mkdir -p ./norm-artifacts ./stable-artifacts ./tree-artifacts
rm -rf ./norm-artifacts
mkdir -p ./norm-artifacts
find ./artifacts -type f -name 'kolibrios-*' | while read -r file; do
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<suffix>
case "$fname" in
*.tree.tar.gz) stem="${fname%.tree.tar.gz}";;
*.distr.zip) stem="${fname%.distr.zip}";;
*.sha256sums.txt) stem="${fname%.sha256sums.txt}";;
*.build.log) stem="${fname%.build.log}";;
*.img) stem="${fname%.img}";;
*.iso) stem="${fname%.iso}";;
*.raw) stem="${fname%.raw}";;
*) continue;;
esac
lang="${stem##*-}" # <lang> has no dashes, <descr> may
find ./artifacts -type f \( \
-name 'kolibrios-*.img' -o \
-name 'kolibrios-*.iso' -o \
-name 'kolibrios-*.raw' \
\) | while read -r file; do
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<ext>
name_without_ext="${fname%.*}"
lang="${name_without_ext##*-}"
mkdir -p "./norm-artifacts/$lang"
case "$fname" in
*.tree.tar.gz)
# unpacked on the server into <version>/<lang>/data/ for per-program downloads
cp "$file" "./tree-artifacts/$lang.tar.gz";;
*.sha256sums.txt)
cp "$file" "./norm-artifacts/$lang/sha256sums.txt";;
*.build.log)
cp "$file" "./norm-artifacts/$lang/build.log";;
*.img)
cp "$file" "./norm-artifacts/$lang/$fname"
# emulators (e.g. v86) hardcode <lang>/data/data/kolibri.img at the site root
mkdir -p "./stable-artifacts/$lang/data/data"
cp "$file" "./stable-artifacts/$lang/data/data/kolibri.img";;
*)
cp "$file" "./norm-artifacts/$lang/$fname";;
esac
cp "$file" "./norm-artifacts/$lang/$fname"
done
# derive the version (git describe) from an artifact name: kolibrios-<descr>-<lang>.iso -> <descr>
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*.iso' | head -n1)"
# derive the version (git describe) from an artifact name:
# kolibrios-<descr>-<lang>.<ext> -> <descr>
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*' | head -n1)"
base="$(basename "${sample%.*}")" # kolibrios-<descr>-<lang>
version="${base%-*}" # kolibrios-<descr>
version="${version#kolibrios-}" # <descr>
echo "version=$version" >> $GITEA_OUTPUT
find ./norm-artifacts ./stable-artifacts ./tree-artifacts -type f -print
find ./norm-artifacts -type f -print
- name: Setup SSH
run: |
@@ -344,6 +285,4 @@ jobs:
-e "storage_path=${{ secrets.STORAGE_PATH }}" \
-e "version=${{ steps.normalize.outputs.version }}" \
-e "artifact_path=${{ gitea.workspace }}/norm-artifacts" \
-e "stable_artifact_path=${{ gitea.workspace }}/stable-artifacts" \
-e "tree_artifact_path=${{ gitea.workspace }}/tree-artifacts" \
-v
+1 -1
View File
@@ -64,7 +64,7 @@ jobs:
make -f Makefile.lin32
chmod +x c--
mv c-- /home/autobuild/tools/win32/bin/c--
cp ${{ gitea.workspace }}/programs/develop/cmm/c--.ini /home/autobuild/tools/win32/bin/c--.ini
cp ${{ gitea.workspace }}/programs/cmm/c--/c--.ini /home/autobuild/tools/win32/bin/c--.ini
make -f Makefile.lin32 clean
- name: Install TCC
+4 -5
View File
@@ -24,8 +24,6 @@ jobs:
path: programs/develop/cmm
- name: oberon07
path: programs/develop/oberon07
- name: cmm_apps
path: programs/cmm
- name: kterm
path: programs/other/kterm
@@ -34,10 +32,11 @@ jobs:
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.BOT_TOKEN }}
- name: Bump ${{ matrix.name }} and open PR
env:
TOKEN: ${{ secrets.GITEA_TOKEN }}
TOKEN: ${{ secrets.BOT_TOKEN }}
API: ${{ github.api_url }}
REPO: ${{ github.repository }}
NAME: ${{ matrix.name }}
@@ -69,7 +68,7 @@ jobs:
git config user.name "kolibri-bot"
git config user.email "bot@kolibrios.org"
git checkout -B "$BRANCH"
git commit -m "chore/submodules: bump $NAME to $WANT" -- "$PATH_"
git commit -m "$NAME: bump submodule to $WANT" -- "$PATH_"
git push -f origin "$BRANCH"
# Open a PR via the Gitea API.
@@ -78,7 +77,7 @@ jobs:
http=$(curl -sS -o /tmp/pr.json -w '%{http_code}' -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"chore/submodules: bump ${NAME} to upstream\"}" \
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"${NAME}: bump submodule to upstream\"}" \
"${API}/repos/${REPO}/pulls")
echo "PR API HTTP status: $http"
cat /tmp/pr.json; echo
+1 -5
View File
@@ -4,12 +4,8 @@
branch = main
[submodule "programs/develop/oberon07"]
path = programs/develop/oberon07
url = https://git.kolibrios.org/KolibriOS/oberon-07-compiler.git
url = https://github.com/AntKrotov/oberon-07-compiler.git
branch = master
[submodule "programs/cmm"]
path = programs/cmm
url = https://git.kolibrios.org/KolibriOS/cmm_apps.git
branch = main
[submodule "programs/other/kterm"]
path = programs/other/kterm
url = https://git.kolibrios.org/b00bl1k/kterm.git
-6
View File
@@ -59,12 +59,6 @@ Co-authored-by: ANOTHER-NAME <ANOTHER-NAME@EXAMPLE.COM>
to the end commit message body on a new line.
If you used AI tools while preparing the commit, you are encouraged to include an Assisted-by tag:
```
Assisted-by: AGENT_NAME:MODEL_VERSION
```
### Merge commits
> [!WARNING]
+9 -19
View File
@@ -74,6 +74,7 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
{"WELCOME.HTM", VAR_DATA .. "/" .. build_type .. "/welcome.htm.kpack"},
{"EXAMPLE.ASM", SRC_PROGS .. "/develop/examples/example/rus/example.asm"},
{"DEVELOP/BACKY", SRC_PROGS .. "/develop/backy/Backy_ru"},
{"GAMES/BASEKURS.KLA", build_type .. "/games/basekurs.kla"},
{"File Managers/KFAR.INI", build_type .. "/File Managers/kfar.ini"},
{"GAMES/DESCENT", build_type .. "/games/descent"},
{"SETTINGS/.shell", SRC_PROGS .. "/system/shell/bin/rus/.shell"},
@@ -169,6 +170,8 @@ extra_files = {
{"kolibrios/demos/life2", "common/demos/life2"},
{"kolibrios/demos/relay.lif", "common/demos/relay.lif"},
{"kolibrios/demos/rpento.lif", "common/demos/rpento.lif"},
{"kolibrios/develop/c--/c--.ini", SRC_PROGS .. "/cmm/c--/c--.ini"},
{"kolibrios/develop/c--/manual_c--.htm", SRC_PROGS .. "/cmm/c--/manual_c--.htm"},
{"kolibrios/develop/fpc/", "common/develop/fpc/*"},
{"kolibrios/develop/fpc/examples/", "../programs/develop/fp/examples/src/*"},
{"kolibrios/develop/oberon07/compiler.kex", SRC_PROGS .. "/develop/oberon07/Compiler.kex"},
@@ -191,12 +194,6 @@ extra_files = {
{"kolibrios/develop/tcc/samples/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/*.sh"},
{"kolibrios/develop/tcc/samples/clayer/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/clayer/*"},
{"kolibrios/develop/utils/SPEDump", SRC_PROGS .. "/develop/SPEDump/SPEDump.kex"},
{"kolibrios/develop/XDPascal/", SRC_PROGS .. "/develop/XDPascal/xdpk/*"},
{"kolibrios/develop/XDPascal/projects2025/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/*"},
{"kolibrios/develop/XDPascal/projects2025/Compiler/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/Compiler/*"},
{"kolibrios/develop/XDPascal/projects2026/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2026/*"},
{"kolibrios/develop/XDPascal/source/", SRC_PROGS .. "/develop/XDPascal/xdpk/source/*"},
{"kolibrios/develop/XDPascal/units/", SRC_PROGS .. "/develop/XDPascal/xdpk/units/*"},
{"kolibrios/emul/", "common/emul/*"},
{"kolibrios/emul/dosbox/", "common/emul/DosBox/*"},
{"kolibrios/emul/e80/readme.txt", SRC_PROGS .. "/emulator/e80/readme.txt"},
@@ -296,6 +293,8 @@ extra_files = {
{"kolibrios/utils/vmode", "common/vmode"},
{"kolibrios/utils/texture", "common/utils/texture"},
{"kolibrios/utils/kterm/kterm", VAR_PROGS .. "/other/kterm/kterm"},
{"kolibrios/utils/kterm/serial.sys", VAR_DRVS .. "/serial/serial.sys"},
{"kolibrios/utils/kterm/install.sh", SRC .. "/drivers/serial/install.sh"},
{"kolibrios/utils/cnc_editor/cnc_editor", VAR_PROGS .. "/other/cnc_editor/cnc_editor"},
{"kolibrios/utils/cnc_editor/kolibri.NC", SRC_PROGS .. "/other/cnc_editor/kolibri.NC"},
{"kolibrios/utils/kfm/kfm.ini", "common/File Managers/kfm.ini"},
@@ -429,6 +428,7 @@ tup.append_table(img_files, {
{"DISPTEST", VAR_PROGS .. "/testing/disptest/disptest"},
{"END", VAR_PROGS .. "/system/end/light/end"},
{"ESKIN", VAR_PROGS .. "/system/eskin/eskin"},
{"FSPEED", VAR_PROGS .. "/testing/fspeed/fspeed"},
{"GMON", VAR_PROGS .. "/system/gmon/gmon"},
{"HDD_INFO", VAR_PROGS .. "/system/hdd_info/hdd_info"},
{"KBD", VAR_PROGS .. "/testing/kbd/kbd"},
@@ -437,6 +437,7 @@ tup.append_table(img_files, {
{"LOADDRV", VAR_PROGS .. "/system/loaddrv/loaddrv"},
{"MAGNIFY", VAR_PROGS .. "/system/magnify/magnify"},
{"MADMOUSE", VAR_PROGS .. "/other/madmouse/madmouse"},
{"MGB", VAR_PROGS .. "/testing/mgb/mgb"},
{"MOUSEMUL", VAR_PROGS .. "/system/mousemul/mousemul"},
{"MOUSEPOS", VAR_PROGS .. "/other/mousepos/mousepos"},
{"MYKEY", VAR_PROGS .. "/system/MyKey/MyKey"},
@@ -542,7 +543,7 @@ tup.append_table(img_files, {
{"NETWORK/PING", VAR_PROGS .. "/network/ping/ping"},
{"NETWORK/NETCFG", VAR_PROGS .. "/network/netcfg/netcfg"},
{"NETWORK/NETSTAT", VAR_PROGS .. "/network/netstat/netstat"},
{"NETWORK/NETSURF", VAR_PROGS .. "/network/netsurf/netsurf"},
{"NETWORK/NSINST", VAR_PROGS .. "/network/netsurf/nsinstall"},
{"NETWORK/NSLOOKUP", VAR_PROGS .. "/network/nslookup/nslookup"},
{"NETWORK/PASTA", VAR_PROGS .. "/network/pasta/pasta"},
{"NETWORK/SYNERGYC", VAR_PROGS .. "/network/synergyc/synergyc"},
@@ -573,15 +574,10 @@ tup.append_table(img_files, {
{"DRIVERS/UHCI.SYS", VAR_DRVS .. "/usb/uhci.sys"},
{"DRIVERS/OHCI.SYS", VAR_DRVS .. "/usb/ohci.sys"},
{"DRIVERS/EHCI.SYS", VAR_DRVS .. "/usb/ehci.sys"},
{"DRIVERS/XHCI.SYS", VAR_DRVS .. "/usb/xhci/xhci.sys"},
{"DRIVERS/USBHID.SYS", VAR_DRVS .. "/usb/usbhid/usbhid.sys"},
{"DRIVERS/USBFTDI.SYS", VAR_DRVS .. "/usb/usbftdi/usbftdi.sys"},
{"DRIVERS/USBOTHER.SYS",VAR_DRVS .. "/usb/usbother/usbother.sys"},
{"DRIVERS/USBCDC.SYS", VAR_DRVS .. "/usb/usbnet/usbcdc.sys"},
{"DRIVERS/USBRNDIS.SYS", VAR_DRVS .. "/usb/usbnet/usbrndis.sys"},
{"DRIVERS/USBSTOR.SYS", VAR_DRVS .. "/usb/usbstor.sys"},
{"DRIVERS/RDC.SYS", VAR_DRVS .. "/video/rdc.sys"},
{"DRIVERS/SERIAL.SYS", VAR_DRVS .. "/serial/serial.sys"},
{"DRIVERS/COMMOUSE.SYS", VAR_DRVS .. "/mouse/commouse.sys"},
{"DRIVERS/PS2MOUSE.SYS", VAR_DRVS .. "/mouse/ps2mouse4d/ps2mouse.sys"},
{"DRIVERS/TMPDISK.SYS", VAR_DRVS .. "/disk/tmpdisk.sys"},
@@ -644,8 +640,6 @@ tup.append_table(extra_files, {
{"kolibrios/media/zsea/plugins/rotate.obj", VAR_PROGS .. "/media/zsea/plugins/rotate/rotate.obj"},
{"kolibrios/media/zsea/plugins/scaling.obj", VAR_PROGS .. "/media/zsea/plugins/scaling/scaling.obj"},
{"kolibrios/utils/AMDtemp", VAR_PROGS .. "/system/amd_temp_view/AMDtemp"},
{"kolibrios/utils/fspeed", VAR_PROGS .. "/testing/fspeed/fspeed"},
{"kolibrios/utils/mgb", VAR_PROGS .. "/testing/mgb/mgb"},
{"kolibrios/utils/kfm/kfm", VAR_PROGS .. "/fs/kfm/kfm"},
{"kolibrios/utils/tedit/t_edit", VAR_PROGS .. "/other/t_edit/t_edit"},
{"kolibrios/3D/blocks/block.bin", VAR_PROGS .. "/bcc32/games/blocks/block.bin"},
@@ -655,6 +649,7 @@ tup.append_table(extra_files, {
})
-- For russian build, add russian-only programs.
if build_type == "ru_RU" then tup.append_table(img_files, {
{"GAMES/KLAVISHA", VAR_PROGS .. "/games/klavisha/klavisha"},
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
}) else tup.append_table(img_files, {
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
@@ -663,8 +658,6 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
if build_type == "ru_RU" then tup.append_table(extra_files, {
{"kolibrios/utils/period", VAR_PROGS .. "/other/period/period"},
{"kolibrios/games/Dungeons/Dungeons", VAR_PROGS .. "/games/Dungeons/Dungeons"},
{"kolibrios/games/klavisha/klavisha", VAR_PROGS .. "/games/klavisha/klavisha"},
{"kolibrios/games/klavisha/basekurs.kla", "ru_RU/games/basekurs.kla"},
}) end
end -- tup.getconfig('NO_FASM') ~= 'full'
@@ -688,7 +681,6 @@ tup.append_table(img_files, {
{"EASYSHOT", VAR_PROGS .. "/cmm/misc/easyshot.com"},
{"MOUSECFG", VAR_PROGS .. "/cmm/mousecfg/mousecfg.com"},
{"BARSCFG", VAR_PROGS .. "/cmm/barscfg/barscfg.com"},
{"BBENCH", VAR_PROGS .. "/cmm/bbench/bbench.com"},
{"SEARCH", VAR_PROGS .. "/cmm/misc/search.com"},
{"SYSPANEL", VAR_PROGS .. "/cmm/misc/software_widget.com"},
{"SYSMON", VAR_PROGS .. "/cmm/sysmon/sysmon.com"},
@@ -817,8 +809,6 @@ tup.append_table(extra_files, {
{"kolibrios/utils/minizip/minizip", VAR_PROGS .. "/fs/minizip/minizip"},
{"kolibrios/utils/minizip/miniunz", VAR_PROGS .. "/fs/minizip/miniunz"},
{"kolibrios/develop/c--/c--", VAR_PROGS .. "/develop/cmm/cmm"},
{"kolibrios/develop/c--/c--.ini", SRC_PROGS .. "/develop/cmm/c--.ini"},
{"kolibrios/develop/c--/manual_c--.htm", SRC_PROGS .. "/develop/cmm/manual_c--.htm"},
{"kolibrios/develop/tcc/tcc", VAR_PROGS .. "/develop/ktcc/source/tcc"},
{"kolibrios/develop/sqlite3/sqlite3", VAR_CONTRIB .. "/sdk/sources/sqlite3/shell/sqlite3"},
{"kolibrios/develop/utils/objconv", VAR_PROGS .. "/develop/objconv/objconv"},
+1 -2
View File
@@ -29,7 +29,6 @@ xcf=/sys/media/kiv
rtf=/sys/RtfRead
3ds=/sys/3d/view3ds
asc=/sys/3d/view3ds
stl=/sys/3d/view3ds
lif=/kolibrios/demos/life2
skn=/sys/skincfg
dtp=/sys/skincfg
@@ -48,7 +47,7 @@ mht=/sys/network/WebView
docx=/sys/network/WebView
url=/sys/network/WebView
fb2=/sys/fb2read
kla=/kolibrios/games/klavisha/klavisha
kla=/sys/games/klavisha
pdf=/kolibrios/media/updf
avi=/kolibrios/media/fplay_run
mpg=/kolibrios/media/fplay_run
Binary file not shown.
+1 -2
View File
@@ -174,12 +174,11 @@ sh=/sys/shell
3ds=/sys/3d/view3ds
asc=/sys/3d/view3ds
stl=/sys/3d/view3ds
skn=/sys/skincfg
dtp=/sys/skincfg
lif=/kolibrios/demos/life2
kla=/kolibrios/games/klavisha/klavisha
kla=/sys/games/klavisha
pdf=/kolibrios/media/updf
smc=/kolibrios/emul/zsnes/zsnes
+1 -1
View File
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
Loderunner=/kg/LRL/LRL,41
; 21days=/kg/21days,104 ;rus only
BabyPainter=/kg/BabyPainter,87
Klavisha=/kg/klavisha/klavisha,69
Klavisha=games/klavisha,69
Millioneer=/kg/WHOWTBAM/whowtbam,114
StarTrek71=/kg/sstartrek/SStarTrek
Descent=games/descent
+2 -1
View File
@@ -35,6 +35,7 @@ Console Board=develop/dbgboard,19
PCI Devices=pcidev,38
CPU Info=cpuid,37
Display Test=disptest,113
Benchmark=bbench,121
Graphic Bench=mgb,121
HDD Info=hdd_info,50
File Speed=fspeed,45
Network Speed=network/dl|-test,51
+1 -1
View File
@@ -243,7 +243,7 @@ x=204
y=0
[22]
name=NETSURF
path=/sys/NETWORK/NETSURF
path=/sys/NETWORK/NSINST
param=
ico=125
x=204
-1
View File
@@ -116,7 +116,6 @@
33 HTTPGet |network/httpget
33 Downloader |network/dl
12 WebView Browser |network/webview
12 NetSurf |network/netsurf
#13 **** SERVERS
24 FTP |network/ftpd
#14 **** OTHER
+1 -1
View File
@@ -243,7 +243,7 @@ x=204
y=0
[22]
name=NETSURF
path=/sys/NETWORK/NETSURF
path=/sys/NETWORK/NSINST
param=
ico=125
x=204
-1
View File
@@ -121,7 +121,6 @@
16 HTTPGet |network/httpget
16 Descargas |network/dl
16 Navegador WebView |network/webview
12 NetSurf |network/netsurf
#15 **** OTROS
16 Reloj analвgico |demos/aclock
16 Reloj binario |demos/bcdclk
+2 -1
View File
@@ -35,6 +35,7 @@ Consola de depuracion=develop/dbgboard,19
Dispositivos PCI=pcidev,38
CPU Info=cpuid,37
Prueba de pantalla=disptest,113
Benchmark=bbench,121
Rendimiento grafico=mgb,121
Info de disco=hdd_info,50
Velocidad FS=fspeed,45
Velocidad de red=network/dl|-test,51
+1 -1
View File
@@ -39,7 +39,7 @@ docx=/sys/network/WebView
url=/sys/network/WebView
fb2=/sys/fb2read
mht=/sys/network/WebView
kla=/kolibrios/games/klavisha/klavisha
kla=/sys/games/klavisha
pdf=/kolibrios/media/updf
avi=/kolibrios/media/fplay_run
mpg=/kolibrios/media/fplay_run
+1 -1
View File
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
Loderunner=/kg/LRL/LRL,41
21days=/kg/21days,104 ;rus only
BabyPainter=/kg/BabyPainter,87
Klavisha=/kg/klavisha/klavisha,69
Klavisha=games/klavisha,69
Millioneer=/kg/WHOWTBAM/whowtbam,114
StarTrek71=/kg/sstartrek/SStarTrek
Descent=games/descent
+1 -1
View File
@@ -243,7 +243,7 @@ x=204
y=0
[22]
name=NETSURF
path=/sys/NETWORK/NETSURF
path=/sys/NETWORK/NSINST
param=
ico=125
x=204
+1 -2
View File
@@ -115,7 +115,6 @@
33 HTTPGet |network/httpget
33 Загрузчик |network/dl
12 Браузер WebView |network/webview
12 Браузер NetSurf |network/netsurf
#14 **** Разное
00 Эмуляторы* > |@6
45 Создание скриншотов |scrshoot
@@ -123,7 +122,7 @@
18 FB2 Читалка |fb2read
16 Аналоговые часы |aclock
21 Таблица Менделеева |/kolibrios/utils/period
59 Тренажёр KJIABuIIIA |/kolibrios/games/klavisha/klavisha
59 Тренажёр KJ|ABuIIIA |games/klavisha
16 Бинарные часы |demos/bcdclk
53 Таймер |timer
09 Разархиватор Unz |unz
+2 -1
View File
@@ -35,6 +35,7 @@ AMDtemp=/k/utils/AMDtemp,128
Устройства PCI=pcidev,38
CPU Info=cpuid,37
Тест экрана=disptest,113
Benchmark=bbench,121
Скорость графики=mgb,121
Информация о дисках=hdd_info,50
Скорость ФС=fspeed,45
Скорость сети=network/dl|-test,51
+13 -11
View File
@@ -515,18 +515,20 @@ HDA_AMP_VOLMASK equ 0x7F
; unsolicited event handler
HDA_UNSOL_QUEUE_SIZE equ 64 ; must stay a power of 2 (used as a bitmask for wrap)
HDA_UNSOL_QUEUE_SIZE equ 64
struc HDA_BUS_UNSOLICITED
{
; ring buffer
.queue rd HDA_UNSOL_QUEUE_SIZE * 2 ; 2 dword for each event (res and res_ex)
.rp dd ? ; Read pointer
.wp dd ? ; Write pointer
; ; workqueue
; .work dd ? ;struct work_struct work;
; .bus dd ? ;struct hda_bus ;bus
}
;struc HDA_BUS_UNSOLICITED
;{
; ; ring buffer
; .queue:
; times HDA_UNSOL_QUEUE_SIZE*2 dd ?
; .rp dd ?
; .wp dd ?
;
; ; workqueue
; .work dd ?;struct work_struct work;
; .bus dd ? ;struct hda_bus ;bus
;};
; Helper for automatic ping configuration
AUTO_PIN_MIC equ 0
+18 -67
View File
@@ -654,15 +654,7 @@ end if
stdcall hda_codec_setup_stream, eax, SDO_TAG, 0, 0x11 ; Left & Right channels (Back panel)
;Asper+ ]
if USE_UNSOL_EV = 0
invoke TimerHS, 1, 0, snd_hda_automute, 1
else
; Keep the unsolicited-event mode on the event-driven path. Running
; snd_hda_automute at startup can issue codec commands before the new
; unsolicited-response flow is ready, which hangs some systems.
invoke TimerHS, 1, 0, process_unsol_events, 0
end if
invoke TimerHS, 1, 0, snd_hda_automute, 0
if USE_SINGLE_MODE
mov esi, msgSingleMode
invoke SysMsgBoardStr
@@ -2643,7 +2635,7 @@ proc snd_hda_automute stdcall, data:dword
test eax, eax
jz .out
stdcall snd_hda_read_pin_sense, edx, [data]
stdcall snd_hda_read_pin_sense, edx, 1
test eax, AC_PINSENSE_PRESENCE
jnz @f
xchg ecx, esi
@@ -2672,64 +2664,24 @@ proc snd_hda_automute stdcall, data:dword
endp
; ;Asper remember to add this functions:
; proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
; ;if DEBUG
; ; push esi
; ; mov esi, msgUnsolEvent
; ; invoke SysMsgBoardStr
; ; pop esi
; ;end if
; if USE_UNSOL_EV = 1
; ;Test. Do not make queue, process immediately!
; ;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
; ;and then mute/unmute pin based on the results
; invoke TimerHS, 1, 0, snd_hda_automute, 0
; end if
; ret
; endp
; ;...
align 4
proc snd_hda_queue_unsol_event stdcall, res:dword, res_ex:dword
; Single-producer (HDA IRQ) lock-free enqueue. The caller azx_update_rirb
; only carries EBX across iterations and reloads the rest, and TimerHS
; preserves EBX too - so by using scratch regs only we need no saves.
mov eax, [unsol_events.wp]
lea edx, [eax+1]
and edx, HDA_UNSOL_QUEUE_SIZE - 1 ; next write pos (size must be 2^n)
cmp edx, [unsol_events.rp]
je .full ; ring full -> drop, keep 1 slot free
mov ecx, [res]
mov [unsol_events.queue + eax*8], ecx
mov ecx, [res_ex]
mov [unsol_events.queue + eax*8 + 4], ecx
mov [unsol_events.wp], edx ; publish only after data is stored
invoke TimerHS, 1, 0, process_unsol_events, 0
.full:
ret
;Asper remember to add this functions:
proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
;if DEBUG
; push esi
; mov esi, msgUnsolEvent
; invoke SysMsgBoardStr
; pop esi
;end if
if USE_UNSOL_EV = 1
;Test. Do not make queue, process immediately!
;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
;and then mute/unmute pin based on the results
invoke TimerHS, 1, 0, snd_hda_automute, 0
end if
ret
endp
;...
align 4
proc process_unsol_events stdcall, data:dword
; Runs from TimerHS (single consumer). Uses only EAX (scratch) and calls
; snd_hda_automute, which preserves every register, so nothing is saved.
.loop:
mov eax, [unsol_events.rp]
cmp eax, [unsol_events.wp]
je .done
; The event payload is at [unsol_events.queue + eax*8] (res) and +4 (res_ex).
; Per-pin tag parsing is not implemented yet, so just re-evaluate jack state.
inc eax
and eax, HDA_UNSOL_QUEUE_SIZE - 1
mov [unsol_events.rp], eax
stdcall snd_hda_automute, 0
jmp .loop
.done:
ret
endp
align 4
proc fdword2str stdcall, flags:dword ; bit 0 - skipLeadZeroes; bit 1 - newLine; other bits undefined
@@ -3105,7 +3057,6 @@ aspinlock dd SPINLOCK_FREE
codec CODEC
ctrl AC_CNTRL
unsol_events HDA_BUS_UNSOLICITED
;Asper: BDL must be aligned to 128 according to HDA specification.
pcmout_bdl rd 1
+5 -59
View File
@@ -1,4 +1,4 @@
SERIAL_COMPATIBLE_API_VER = 1 ; increments in case of breaking changes
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
SERIAL_API_GET_VERSION = 0
SERIAL_API_SRV_ADD_PORT = 1
@@ -9,7 +9,6 @@ SERIAL_API_CLOSE_PORT = 5
SERIAL_API_SETUP_PORT = 6
SERIAL_API_READ = 7
SERIAL_API_WRITE = 8
SERIAL_API_ENUM_PORTS = 9
SERIAL_API_ERR_PORT_INVALID = 1
SERIAL_API_ERR_PORT_BUSY = 2
@@ -30,9 +29,6 @@ SERIAL_CONF_STOP_BITS_2 = 2
SERIAL_CONF_FLOW_CTRL_NONE = 0
SERIAL_INFO_DRIVER_LEN = 16
SERIAL_INFO_DESCR_LEN = 64
struct SP_DRIVER
size dd ? ; size of this struct
startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
@@ -50,20 +46,7 @@ struct SP_CONF
flow_ctrl db ?
ends
struct SP_PORT_INFO
size dd ? ; size of this struct
driver dd ? ; ASCIIZ driver name, e.g. "uart16550", "usb-cdc"
descr dd ? ; ASCIIZ description, may be NULL
ends
struct SP_PORT_ENUM_ENTRY
id dd ? ; unique port number (SERIAL_PORT.id)
busy dd ? ; 0 = free, non-zero = port is opened
driver rb SERIAL_INFO_DRIVER_LEN
descr rb SERIAL_INFO_DESCR_LEN
ends
proc serial_add_port stdcall, drv:dword, drv_data:dword, info:dword
proc serial_add_port stdcall, drv:dword, drv_data:dword
locals
handler dd ?
io_code dd ?
@@ -77,7 +60,7 @@ endl
mov [io_code], SERIAL_API_SRV_ADD_PORT
lea eax, [drv]
mov [input], eax
mov [inp_size], 12
mov [inp_size], 8
xor eax, eax
mov [output], eax
mov [out_size], eax
@@ -146,7 +129,7 @@ proc serial_port_init
ret
endp
proc serial_port_get_version stdcall uses ebx, version:dword
proc serial_port_get_version stdcall, version:dword
locals
.handler dd ?
.io_code dd ?
@@ -166,7 +149,7 @@ endl
lea ecx, [.handler]
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
ret
endp
@@ -314,43 +297,6 @@ endl
ret
endp
proc serial_port_enum stdcall uses ebx, buf:dword, buf_size:dword, \
total:dword, filled:dword
locals
.handler dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
endl
push [buf_size]
push [buf]
mov eax, [serial_drv_handle]
mov [.handler], eax
mov dword [.io_code], SERIAL_API_ENUM_PORTS
mov [.input], esp
mov dword [.inp_size], 8
sub esp, 8
mov [.output], esp
mov dword [.out_size], 8
lea ecx, [.handler]
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
pop ebx edx
cmp eax, -1
je .err
mov ecx, [total]
mov [ecx], ebx
mov ecx, [filled]
mov [ecx], edx
.err:
add esp, 8
ret
endp
align 4
serial_drv_name db "SERIAL", 0
serial_drv_handle dd ?
+5
View File
@@ -0,0 +1,5 @@
#SHS
echo Installing serial driver for kterm...
cp /kolibrios/utils/kterm/serial.sys /sys/drivers/
/sys/loaddrv serial
echo Serial driver successfully installed!
+7 -148
View File
@@ -44,8 +44,6 @@ struct SERIAL_PORT
rx_buf RING_BUF
tx_buf RING_BUF
conf SP_CONF
driver rb SERIAL_INFO_DRIVER_LEN ; ASCIIZ, copied from SP_PORT_INFO.driver in add_port
descr rb SERIAL_INFO_DESCR_LEN ; ASCIIZ, copied from SP_PORT_INFO.descr in add_port (may be empty)
ends
proc START c, reason:dword, cmdline:dword
@@ -59,7 +57,7 @@ proc START c, reason:dword, cmdline:dword
stdcall uart_probe, 0x2f8, 3
stdcall uart_probe, 0x3e8, 4
stdcall uart_probe, 0x2e8, 3
invoke RegService, serial_drv_name, service_proc
invoke RegService, drv_name, service_proc
ret
.fail:
@@ -77,7 +75,7 @@ srv_calls:
dd service_proc.setup
dd service_proc.read
dd service_proc.write
dd service_proc.enum_ports
; TODO enumeration
srv_calls_end:
proc service_proc stdcall uses ebx esi edi, ioctl:dword
@@ -99,13 +97,11 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
; in:
; +0: driver
; +4: driver data
; +8: port info (SP_PORT_INFO*)
cmp [edx + IOCTL.inp_size], 12
cmp [edx + IOCTL.inp_size], 8
jb .err
mov ebx, [edx + IOCTL.input]
mov ecx, [ebx]
mov edx, [ebx + 4]
mov ebx, [ebx + 8]
call add_port
ret
@@ -141,7 +137,6 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
; +4 addr to SERIAL_CONF
; out:
; +0 port handle if success
; eax = 0 if success, otherwise an error code SERIAL_API_ERR_*
cmp [edx + IOCTL.inp_size], 8
jb .err
cmp [edx + IOCTL.out_size], 4
@@ -225,60 +220,25 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
mov [ebx], ecx
ret
.enum_ports:
; in:
; +0 output buffer (array of SP_PORT_ENUM_ENTRY), may be NULL
; +4 output buffer size in bytes
; out:
; +0 total number of ports in the system
; +4 number of entries actually filled into the buffer
; eax = 0 if success, -1 otherwise
cmp [edx + IOCTL.inp_size], 8
jb .err
cmp [edx + IOCTL.out_size], 8
jb .err
mov ebx, [edx + IOCTL.input]
push edx
mov eax, [ebx]
mov edx, [ebx + 4]
call sp_enum
pop edx
mov ebx, [edx + IOCTL.output]
mov [ebx], eax
mov [ebx + 4], ecx
xor eax, eax
ret
.err:
or eax, -1
ret
endp
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
align 4
; @param ecx pointer to SP_DRIVER
; @param edx driver-specific argument
; @param ebx pointer to SP_PORT_INFO
; @return SERIAL_PORT descriptor
proc add_port uses edi
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x info=%x\n", ecx, edx, ebx
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
mov eax, [ecx + SP_DRIVER.size]
cmp eax, sizeof.SP_DRIVER
jne .fail
test ebx, ebx
jz .fail
mov eax, [ebx + SP_PORT_INFO.size]
cmp eax, sizeof.SP_PORT_INFO
jne .fail
; alloc memory for serial port descriptor
push ecx
push edx
push ebx
movi eax, sizeof.SERIAL_PORT
invoke Kmalloc
pop ebx
pop edx
pop ecx
test eax, eax
@@ -292,17 +252,6 @@ proc add_port uses edi
invoke MutexInit
and [edi + SERIAL_PORT.con], 0
; copy port info strings
mov eax, [ebx + SP_PORT_INFO.driver]
lea edx, [edi + SERIAL_PORT.driver]
mov ecx, SERIAL_INFO_DRIVER_LEN
call copy_bounded_str
mov eax, [ebx + SP_PORT_INFO.descr]
lea edx, [edi + SERIAL_PORT.descr]
mov ecx, SERIAL_INFO_DESCR_LEN
call copy_bounded_str
mov ecx, port_list_mutex
invoke MutexLock
@@ -333,35 +282,7 @@ proc add_port uses edi
endp
align 4
; copies an ASCIIZ string into a fixed-size buffer: copies up to (size - 1)
; bytes or until the NUL, then zero-pads the rest of the buffer
; @param eax source ASCIIZ ptr, may be NULL
; @param edx dest buffer ptr
; @param ecx dest buffer size in bytes, must be >= 1
proc copy_bounded_str uses esi edi
mov esi, eax
mov edi, edx
dec ecx ; reserve the last byte for the NUL terminator
.copy:
test ecx, ecx
jz .pad
test esi, esi
jz .pad
lodsb
test al, al
jz .pad
stosb
dec ecx
jmp .copy
.pad:
inc ecx ; account for the reserved NUL byte
xor al, al
rep stosb
ret
endp
align 4
; @param ecx serial port descriptor
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
proc remove_port uses esi
mov esi, ecx
mov ecx, port_list_mutex
@@ -736,69 +657,7 @@ proc sp_write
ret
endp
align 4
; @param eax buf
; @param edx buf_size (bytes)
; @return eax total port count in the system
; ecx entries filled into buf
proc sp_enum uses ebx esi edi
mov ecx, eax
mov eax, edx
xor edx, edx
mov ebx, sizeof.SP_PORT_ENUM_ENTRY
div ebx
; eax max entries count
mov edi, ecx
imul eax, sizeof.SP_PORT_ENUM_ENTRY
add eax, ecx
mov edx, eax ; end-of-buffer boundary
xor ebx, ebx ; total port count
xor ecx, ecx ; filled count
push ecx edx
mov ecx, port_list_mutex
invoke MutexLock
pop edx ecx
mov esi, port_list
.next:
mov esi, [esi + SERIAL_PORT.fd]
cmp esi, port_list
jz .done
inc ebx
cmp edi, edx
jae .next
mov eax, [esi + SERIAL_PORT.id]
mov [edi + SP_PORT_ENUM_ENTRY.id], eax
xor eax, eax
cmp dword [esi + SERIAL_PORT.con], 0
setnz al
mov [edi + SP_PORT_ENUM_ENTRY.busy], eax
push ecx esi edi
lea esi, [esi + SERIAL_PORT.driver]
lea edi, [edi + SP_PORT_ENUM_ENTRY.driver]
mov ecx, (SERIAL_INFO_DRIVER_LEN + SERIAL_INFO_DESCR_LEN) / 4
rep movsd
pop edi esi ecx
add edi, sizeof.SP_PORT_ENUM_ENTRY
inc ecx
jmp .next
.done:
push ecx
mov ecx, port_list_mutex
invoke MutexUnlock
pop ecx
mov eax, ebx
ret
endp
drv_name db 'SERIAL', 0
include_debug_strings
align 4
-9
View File
@@ -169,7 +169,6 @@ proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
; register port
lea ecx, [uart_drv]
mov edx, edi
lea ebx, [uart_port_info]
call add_port
test eax, eax
jz .free_desc ; TODO detach_int_handler?
@@ -407,11 +406,3 @@ uart_drv:
dd uart_reconf
dd uart_tx
uart_drv_end:
align 4
uart_port_info:
dd uart_port_end - uart_port_info
dd uart_port_name
dd 0
uart_port_end:
uart_port_name db 'uart16550', 0
+310 -203
View File
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FTDI chips driver for KolibriOS ;;
@@ -15,11 +15,10 @@
format PE DLL native 0.05
entry START
L_DBG = 1
L_ERR = 2
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = L_ERR
__DEBUG_LEVEL__ = 1
node equ ftdi_context
node.next equ ftdi_context.next_context
@@ -123,10 +122,9 @@ TYPE_232H=6
TYPE_230X=7
;strings
my_driver db 'usbftdi',0
my_driver db 'usbother',0
serial_driver db 'SERIAL',0
nomemory_msg db 'ftdi: no memory',13,10,0
ftdi_port_name db 'ftdi',0
nomemory_msg db 'K : no memory',13,10,0
; Structures
struct ftdi_context
@@ -202,13 +200,10 @@ endp
proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
locals
.pinfo rb sizeof.SP_PORT_INFO
endl
invoke USBGetParam, [.config_pipe], 0
mov edx, eax
DEBUGF L_DBG, 'ftdi: Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
cmp word[eax+usb_descr.idVendor], 0x0403
jnz .notftdi
mov eax, sizeof.ftdi_context
@@ -219,7 +214,7 @@ endl
invoke SysMsgBoardStr
jmp .nothing
@@:
DEBUGF L_DBG, 'ftdi: Adding struct to list 0x%x\n', eax
DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
call linkedlist_add
mov ebx, [.config_pipe]
@@ -238,7 +233,7 @@ endl
jmp .slow
mov cx, [edx+usb_descr.bcdDevice]
DEBUGF L_DBG, 'ftdi: Chip type 0x%x\n', ecx
DEBUGF 2, 'K : Chip type 0x%x\n', ecx
cmp cx, 0x400
jnz @f
mov [eax + ftdi_context.chipType], TYPE_BM
@@ -292,13 +287,8 @@ endl
mov eax, [serial_drv_entry]
test eax, eax
jz @f
mov dword [.pinfo + SP_PORT_INFO.size], sizeof.SP_PORT_INFO
mov dword [.pinfo + SP_PORT_INFO.driver], ftdi_port_name
; TODO obtain iManufacturer, iProduct and iSerial strings
mov dword [.pinfo + SP_PORT_INFO.descr], 0
lea ecx, [.pinfo]
stdcall serial_add_port, uart_drv, ebx, ecx
DEBUGF L_DBG, 'ftdi: add serial port with result %x\n', eax
stdcall serial_add_port, uart_drv, ebx
DEBUGF 1, "usbftdi: add serial port with result %x\n", eax
@@:
mov [ebx + ftdi_context.port_handle], eax
@@ -306,7 +296,7 @@ endl
ret
.notftdi:
DEBUGF L_DBG, 'ftdi: Skipping not FTDI device\n'
DEBUGF 1,'K : Skipping not FTDI device\n'
.nothing:
xor eax, eax
ret
@@ -327,7 +317,7 @@ EventData rd 3
endl
mov edi, [ioctl]
mov eax, [edi+io_code]
DEBUGF L_DBG, 'ftdi: FTDI got the request: %d\n', eax
DEBUGF 1,'K : FTDI got the request: %d\n', eax
test eax, eax ;0
jz .version
dec eax ;1
@@ -426,7 +416,7 @@ endl
.version:
jmp .endswitch
.error:
DEBUGF L_ERR, 'ftdi: error occured! %d\n', eax
DEBUGF 1, 'K : FTDI error occured! %d\n', eax
;mov esi, [edi+output]
;mov [esi], dword 'ERR0'
;or [esi], eax
@@ -459,7 +449,7 @@ endl
mov word[ConfPacket+6], cx
.own_index:
mov ebx, [edi+4]
DEBUGF L_DBG, 'ftdi: ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
lea esi, [ConfPacket]
lea edi, [EventData]
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
@@ -475,7 +465,7 @@ endl
jmp .error
.ftdi_setrtshigh:
DEBUGF L_DBG, 'ftdi: Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -483,7 +473,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_setrtslow:
DEBUGF L_DBG, 'ftdi: Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -491,7 +481,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_setdtrhigh:
DEBUGF L_DBG, 'ftdi: Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -499,7 +489,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_setdtrlow:
DEBUGF L_DBG, 'ftdi: Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
@@ -507,7 +497,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_usb_reset:
DEBUGF L_DBG, 'ftdi: Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_RESET_REQUEST shl 8) \
@@ -515,7 +505,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_purge_rx_buf:
DEBUGF L_DBG, 'ftdi: Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_RESET_REQUEST shl 8) \
@@ -523,7 +513,7 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_purge_tx_buf:
DEBUGF L_DBG, 'ftdi: Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_RESET_REQUEST shl 8) \
@@ -531,42 +521,42 @@ endl
jmp .ftdi_out_control_transfer_noinp
.ftdi_set_bitmode:
DEBUGF L_DBG, 'ftdi: Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
[edi+8]:2,[edi+10]:2,[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_BITMODE_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_line_property:
DEBUGF L_DBG, 'ftdi: Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
[edi+8]:4,[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_DATA_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_latency_timer:
DEBUGF L_DBG, 'ftdi: Set latency %d PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
[edi+8],[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_event_char:
DEBUGF L_DBG, 'ftdi: Set event char %c PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
[edi+8],[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_EVENT_CHAR_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_set_error_char:
DEBUGF L_DBG, 'ftdi: Set error char %c PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
[edi+8],[edi],[edi+4]
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_ERROR_CHAR_REQUEST shl 8)
jmp .ftdi_out_control_transfer_withinp
.ftdi_setflowctrl:
DEBUGF L_DBG, 'ftdi: Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
@@ -579,7 +569,7 @@ endl
jmp .own_index
.ftdi_read_pins:
DEBUGF L_DBG, 'ftdi: Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov ebx, [edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
@@ -608,7 +598,7 @@ endl
jmp .error
.ftdi_set_wchunksize:
DEBUGF L_DBG, 'ftdi: Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
[edi+8], [edi], [edi+4]
mov ebx, [edi+4]
mov ecx, [edi+8]
@@ -618,7 +608,7 @@ endl
jmp .endswitch
.ftdi_get_wchunksize:
DEBUGF L_DBG, 'ftdi: Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov esi, [edi+output]
mov edi, [edi+input]
@@ -628,7 +618,7 @@ endl
jmp .endswitch
.ftdi_set_rchunksize:
DEBUGF L_DBG, 'ftdi: Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
[edi+8], [edi], [edi+4]
mov ebx, [edi+4]
mov ecx, [edi+8]
@@ -638,7 +628,7 @@ endl
jmp .endswitch
.ftdi_get_rchunksize:
DEBUGF L_DBG, 'ftdi: Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov esi, [edi+output]
mov edi, [edi+input]
@@ -648,7 +638,7 @@ endl
jmp .endswitch
.ftdi_write_data:
DEBUGF L_DBG, 'ftdi: Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
[edi], [edi+4]
mov esi, edi
add esi, 12
@@ -695,7 +685,7 @@ endl
jmp .write_loop
.ftdi_read_data:
DEBUGF L_DBG, 'ftdi: Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
[edi], [edi+4]
mov edi, [ioctl]
mov esi, [edi+input]
@@ -753,7 +743,7 @@ endl
;---Dirty hack end
.ftdi_poll_modem_status:
DEBUGF L_DBG, 'ftdi: Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov ebx, [edi+4]
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
@@ -777,7 +767,7 @@ endl
jmp .endswitch
.ftdi_get_latency_timer:
DEBUGF L_DBG, 'ftdi: Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
[edi+4]
mov ebx, [edi+4]
mov dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
@@ -797,7 +787,7 @@ endl
jmp .endswitch
.ftdi_get_list:
DEBUGF L_DBG, 'ftdi: devices list request\n'
DEBUGF 2, 'K : FTDI devices list request\n'
mov edi, [edi+output]
xor ecx, ecx
call linkedlist_gethead
@@ -827,7 +817,7 @@ endl
jmp .endswitch
.ftdi_lock:
DEBUGF L_DBG, 'ftdi: Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
mov esi, [edi+input]
mov ebx, [esi+4]
mov eax, [ebx + ftdi_context.lockPID]
@@ -841,7 +831,7 @@ endl
jmp .endswitch
.ftdi_unlock:
DEBUGF L_DBG, 'ftdi: Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
mov esi, [edi+input]
mov edi, [edi+output]
mov ebx, [esi+4]
@@ -855,19 +845,145 @@ endl
mov [edi], eax
jmp .endswitch
H_CLK = 120000000
C_CLK = 48000000
.ftdi_set_baudrate:
DEBUGF L_DBG, 'ftdi: Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
[edi+8], [edi], [edi+4]
mov ebx, [edi+4]
mov esi, [edi+8]
call ftdi_calc_baud_divisor
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk
imul eax, [edi+8], 10
cmp eax, H_CLK / 0x3FFF
jle .c_clk
.h_clk:
cmp dword[edi+8], H_CLK/10
jl .h_nextbaud1
xor edx, edx
mov ecx, H_CLK/10
jmp .calcend
.c_clk:
cmp dword[edi+8], C_CLK/16
jl .c_nextbaud1
xor edx, edx
mov ecx, C_CLK/16
jmp .calcend
.h_nextbaud1:
cmp dword[edi+8], H_CLK/(10 + 10/2)
jl .h_nextbaud2
mov edx, 1
mov ecx, H_CLK/(10 + 10/2)
jmp .calcend
.c_nextbaud1:
cmp dword[edi+8], C_CLK/(16 + 16/2)
jl .c_nextbaud2
mov edx, 1
mov ecx, C_CLK/(16 + 16/2)
jmp .calcend
.h_nextbaud2:
cmp dword[edi+8], H_CLK/(2*10)
jl .h_nextbaud3
mov edx, 2
mov ecx, H_CLK/(2*10)
jmp .calcend
.c_nextbaud2:
cmp dword[edi+8], C_CLK/(2*16)
jl .c_nextbaud3
mov edx, 2
mov ecx, C_CLK/(2*16)
jmp .calcend
.h_nextbaud3:
mov eax, H_CLK*16/10 ; eax - best_divisor
xor edx, edx
div dword[edi+8] ; [edi+8] - baudrate
push eax
and eax, 1
pop eax
shr eax, 1
jz .h_rounddowndiv ; jump by result of and eax, 1
inc eax
.h_rounddowndiv:
cmp eax, 0x20000
jle .h_best_divok
mov eax, 0x1FFFF
.h_best_divok:
mov ecx, eax
mov eax, H_CLK*16/10
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jz .rounddownbaud
inc ecx
jmp .rounddownbaud
.c_nextbaud3:
mov eax, C_CLK ; eax - best_divisor
xor edx, edx
div dword[edi+8] ; [edi+8] - baudrate
push eax
and eax, 1
pop eax
shr eax, 1
jnz .c_rounddowndiv ; jump by result of and eax, 1
inc eax
.c_rounddowndiv:
cmp eax, 0x20000
jle .c_best_divok
mov eax, 0x1FFFF
.c_best_divok:
mov ecx, eax
mov eax, C_CLK
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jnz .rounddownbaud
inc ecx
.rounddownbaud:
mov edx, eax ; edx - encoded_divisor
shr edx, 3
and eax, 0x7
push 7 6 5 1 4 2 3 0
mov eax, [esp+eax*4]
shl eax, 14
or edx, eax
add esp, 32
.calcend:
mov eax, edx ; eax - *value
mov ecx, edx ; ecx - *index
and eax, 0xFFFF
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jge .foxyindex
shr ecx, 16
jmp .preparepacket
.foxyindex:
shr ecx, 8
and ecx, 0xFF00
or ecx, [ebx + ftdi_context.index]
.preparepacket:
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
mov word[ConfPacket+2], ax
mov word[ConfPacket+4], cx
mov word[ConfPacket+6], 0
jmp .own_index
jmp .own_index
endp
restore handle
restore io_code
@@ -877,143 +993,10 @@ restore output
restore out_size
proc ftdi_calc_baud_divisor
; in: ebx = ftdi_context pointer
; esi = baud rate
; out: ax = encoded value
; cx = encoded index
; destroys: eax, ecx, edx, esi
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk
imul eax, esi, 10
cmp eax, H_CLK / 0x3FFF
jle .c_clk
.h_clk:
cmp esi, H_CLK / 10
jl .h_nextbaud1
xor edx, edx
mov ecx, H_CLK / 10
jmp .calcend
.c_clk:
cmp esi, C_CLK / 16
jl .c_nextbaud1
xor edx, edx
mov ecx, C_CLK / 16
jmp .calcend
.h_nextbaud1:
cmp esi, H_CLK / (10 + 10 / 2)
jl .h_nextbaud2
mov edx, 1
mov ecx, H_CLK / (10 + 10 / 2)
jmp .calcend
.c_nextbaud1:
cmp esi, C_CLK / (16 + 16 / 2)
jl .c_nextbaud2
mov edx, 1
mov ecx, C_CLK/(16 + 16 / 2)
jmp .calcend
.h_nextbaud2:
cmp esi, H_CLK / (2 * 10)
jl .h_nextbaud3
mov edx, 2
mov ecx, H_CLK / (2 * 10)
jmp .calcend
.c_nextbaud2:
cmp esi, C_CLK / (2 * 16)
jl .c_nextbaud3
mov edx, 2
mov ecx, C_CLK / (2 * 16)
jmp .calcend
.h_nextbaud3:
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
xor edx, edx
div esi
push eax
and eax, 1
pop eax
shr eax, 1
jz .h_rounddowndiv ; jump by result of and eax, 1
inc eax
.h_rounddowndiv:
cmp eax, 0x20000
jle .h_best_divok
mov eax, 0x1FFFF
.h_best_divok:
mov ecx, eax
mov eax, H_CLK * 16 / 10
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jz .rounddownbaud
inc ecx
jmp .rounddownbaud
.c_nextbaud3:
mov eax, C_CLK ; eax - best_divisor
xor edx, edx
div esi
push eax
and eax, 1
pop eax
shr eax, 1
jnz .c_rounddowndiv ; jump by result of and eax, 1
inc eax
.c_rounddowndiv:
cmp eax, 0x20000
jle .c_best_divok
mov eax, 0x1FFFF
.c_best_divok:
mov ecx, eax
mov eax, C_CLK
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jnz .rounddownbaud
inc ecx
.rounddownbaud:
mov edx, eax ; edx - encoded_divisor
shr edx, 3
and eax, 0x7
push 7 6 5 1 4 2 3 0
mov eax, [esp + eax * 4]
shl eax, 14
or edx, eax
add esp, 32
.calcend:
mov eax, edx ; eax - *value
mov ecx, edx ; ecx - *index
and eax, 0xFFFF
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jge .foxyindex
shr ecx, 16
ret
.foxyindex:
shr ecx, 8
and ecx, 0xFF00
or ecx, [ebx + ftdi_context.index]
ret
endp
proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
.buffer:DWORD, .length:DWORD, .calldata:DWORD
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
DEBUGF 1, 'K : status is %d\n', [.status]
mov ecx, [.calldata]
mov eax, [ecx]
mov ebx, [ecx+4]
@@ -1028,7 +1011,7 @@ endp
proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
.buffer:DWORD, .length:DWORD, .calldata:DWORD
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
DEBUGF 1, 'K : status is %d\n', [.status]
mov ecx, [.calldata]
mov eax, [ecx]
mov ebx, [ecx+4]
@@ -1051,7 +1034,7 @@ endp
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
DEBUGF L_DBG, 'ftdi: deleting device data 0x%x\n', [.device_data]
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
mov esi, [.device_data]
mov eax, [esi + ftdi_context.readBufPtr]
test eax, eax
@@ -1079,7 +1062,7 @@ proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
mov eax, [.status]
test eax, eax
jz @f
DEBUGF L_ERR, 'ftdi: bulk in error %x\n', eax
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
@@:
mov ebx, [.calldata]
btr dword [ebx + ftdi_context.writeBufLock], 0
@@ -1092,7 +1075,7 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
mov eax, [.status]
test eax, eax
jz @f
DEBUGF L_ERR, 'ftdi: bulk out error %x\n', eax
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
@@:
mov ebx, [.calldata]
mov ecx, [.length]
@@ -1109,18 +1092,18 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
endp
proc uart_startup stdcall uses ebx, data:dword, conf:dword
DEBUGF L_DBG, "ftdi: startup %x %x\n", [data], [conf]
DEBUGF 1, "ftdi: startup %x %x\n", [data], [conf]
stdcall uart_reconf, [data], [conf]
test eax, eax
jz @f
DEBUGF L_ERR, "ftdi: uart reconf error %x\n", eax
DEBUGF 2, "ftdi: uart reconf error %x\n", eax
jmp .exit
@@:
mov ebx, [data]
invoke TimerHS, 2, 2, uart_rx, ebx
test eax, eax
jnz @f
DEBUGF L_ERR, "ftdi: timer creation error\n"
DEBUGF 2, "ftdi: timer creation error\n"
or eax, -1
jmp .exit
@@:
@@ -1131,7 +1114,7 @@ proc uart_startup stdcall uses ebx, data:dword, conf:dword
endp
proc uart_shutdown stdcall uses ebx, data:dword
DEBUGF L_DBG, "ftdi: shutdown %x\n", [data]
DEBUGF 1, "ftdi: shutdown %x\n", [data]
mov ebx, [data]
cmp [ebx + ftdi_context.rx_timer], 0
jz @f
@@ -1263,14 +1246,137 @@ proc uart_rx stdcall uses ebx esi, data:dword
ret
endp
proc ftdi_set_baudrate stdcall uses ebx esi, dev:dword, baud:dword
proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
locals
ConfPacket rb 8
endl
mov ebx, [dev]
mov esi, [baud]
call ftdi_calc_baud_divisor
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jl .c_clk
imul eax, [baud], 10
cmp eax, H_CLK / 0x3FFF
jle .c_clk
.h_clk:
cmp dword [baud], H_CLK / 10
jl .h_nextbaud1
xor edx, edx
mov ecx, H_CLK / 10
jmp .calcend
.c_clk:
cmp dword [baud], C_CLK / 16
jl .c_nextbaud1
xor edx, edx
mov ecx, C_CLK / 16
jmp .calcend
.h_nextbaud1:
cmp dword [baud], H_CLK / (10 + 10 / 2)
jl .h_nextbaud2
mov edx, 1
mov ecx, H_CLK / (10 + 10 / 2)
jmp .calcend
.c_nextbaud1:
cmp dword [baud], C_CLK / (16 + 16 / 2)
jl .c_nextbaud2
mov edx, 1
mov ecx, C_CLK/(16 + 16 / 2)
jmp .calcend
.h_nextbaud2:
cmp dword [baud], H_CLK / (2 * 10)
jl .h_nextbaud3
mov edx, 2
mov ecx, H_CLK / (2 * 10)
jmp .calcend
.c_nextbaud2:
cmp dword [baud], C_CLK / (2 * 16)
jl .c_nextbaud3
mov edx, 2
mov ecx, C_CLK / (2 * 16)
jmp .calcend
.h_nextbaud3:
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
xor edx, edx
div dword [baud]
push eax
and eax, 1
pop eax
shr eax, 1
jz .h_rounddowndiv ; jump by result of and eax, 1
inc eax
.h_rounddowndiv:
cmp eax, 0x20000
jle .h_best_divok
mov eax, 0x1FFFF
.h_best_divok:
mov ecx, eax
mov eax, H_CLK * 16 / 10
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jz .rounddownbaud
inc ecx
jmp .rounddownbaud
.c_nextbaud3:
mov eax, C_CLK ; eax - best_divisor
xor edx, edx
div dword [baud]
push eax
and eax, 1
pop eax
shr eax, 1
jnz .c_rounddowndiv ; jump by result of and eax, 1
inc eax
.c_rounddowndiv:
cmp eax, 0x20000
jle .c_best_divok
mov eax, 0x1FFFF
.c_best_divok:
mov ecx, eax
mov eax, C_CLK
xor edx, edx
div ecx
xchg ecx, eax ; ecx - best_baud
push ecx
and ecx, 1
pop ecx
shr ecx, 1
jnz .rounddownbaud
inc ecx
.rounddownbaud:
mov edx, eax ; edx - encoded_divisor
shr edx, 3
and eax, 0x7
push 7 6 5 1 4 2 3 0
mov eax, [esp + eax * 4]
shl eax, 14
or edx, eax
add esp, 32
.calcend:
mov eax, edx ; eax - *value
mov ecx, edx ; ecx - *index
and eax, 0xFFFF
cmp [ebx + ftdi_context.chipType], TYPE_2232H
jge .foxyindex
shr ecx, 16
jmp .preparepacket
.foxyindex:
shr ecx, 8
and ecx, 0xFF00
or ecx, [ebx + ftdi_context.index]
.preparepacket:
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
mov word [ConfPacket + 2], ax
@@ -1345,9 +1451,10 @@ uart_drv:
dd uart_tx
uart_drv_end:
include_debug_strings
serial_drv_entry dd 0
data fixups
end data
serial_drv_entry dd ?
;for DEBUGF macro
include_debug_strings
-3
View File
@@ -1,3 +0,0 @@
if tup.getconfig("NO_FASM") ~= "" then return end
ROOT = "../../.."
tup.foreach_rule("*.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+2 -12
View File
@@ -79,7 +79,7 @@ macro ADD_CLASS drv_name, class, subclass, protocol {
..class_code = ..length or (class shl 8)
if ..length = 3
..class_code = ..class_code or (subclass shl 16) or (protocol shl 24)
..class_code = ..class_code or (protocol shl 24)
end if
if ..length = 2
..class_code = ..class_code or (subclass shl 16)
@@ -172,17 +172,7 @@ macro ADD_IDL drv_name, [vendor_id, device_id] {
INIT_USBDRV_FILE
; CDC (Communications Device Class): NCM network + ACM serial
ADD_CLASS 'usbcdc' , 0x02, X , X
; RNDIS network (Remote NDIS): LTE modems in HiLink mode, USB tethering.
; Three encodings exist: Wireless-Controller/RF/RNDIS, Miscellaneous/
; RNDIS-over-Ethernet (phone tethering) and an ACM masquerade (the
; latter is declined by usbcdc, so the scan falls through to us).
ADD_CLASS 'usbrndis' , 0xE0, 0x01, 0x03
ADD_CLASS 'usbrndis' , 0xEF, 0x04, 0x01
ADD_CLASS 'usbrndis' , 0x02, 0x02, 0xFF
;ADD_CLASS 'usbcdc-ctrl' , 0x02, X , X
;ADD_CLASS 'usbimage' , 0x06, 1 , 1
;ADD_CLASS 'usbcdc-data' , 0x0A, X , X
;ADD_CLASS 'ccid' , 0x0B, X , X
+2 -476
View File
@@ -722,225 +722,6 @@ endp
; callback inquiry_callback;
; * inquiry_callback checks that a logical device is a block device
; and the unit was ready; if so, it notifies the kernel about new disk device.
; Open the bulk pipes of the Zero-CD device and send the switch message
; chosen for it (optionally preceded by an INQUIRY exchange). Used as
; the fallback when the device has no MS OS 2.0 alternate enumeration.
proc modeswitch_send_cbw
push ebx
mov ebx, [modeswitch_pipe0]
cmp dword [modeswitch_in_ep], 0
jz @f
invoke USBOpenPipe, ebx, [modeswitch_in_ep], [modeswitch_in_mps], \
BULK_PIPE, 0
mov [modeswitch_in_pipe], eax
@@:
invoke USBOpenPipe, ebx, [modeswitch_out_ep], [modeswitch_out_mps], \
BULK_PIPE, 0
test eax, eax
jz .fail
mov [modeswitch_out_pipe], eax
; warm up the firmware with an INQUIRY exchange first, if the method
; asks for it (and the CSW pipe is available)
cmp dword [modeswitch_inq], 0
jz .magic
cmp dword [modeswitch_in_pipe], 0
jz .magic
invoke USBNormalTransferAsync, eax, modeswitch_cbw_inq, 31, \
modeswitch_inq_cbw_callback, 0, 0
DEBUGF 1,'K : modeswitch INQUIRY CBW submitted, handle %x\n', eax
test eax, eax
jz .fail
pop ebx
ret
.magic:
invoke USBNormalTransferAsync, [modeswitch_out_pipe], [modeswitch_msg], 31, \
modeswitch_callback, 0, 0
DEBUGF 1,'K : modeswitch CBW submitted, handle %x\n', eax
test eax, eax
jz .fail
pop ebx
ret
.fail:
mov dword [modeswitch_pipe0], 0 ; transaction over
pop ebx
ret
endp
; The INQUIRY CBW went out: read the 36 data bytes.
proc modeswitch_inq_cbw_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch INQUIRY CBW done, status %d\n', [.status]
cmp [.status], 0
jne .fail
invoke USBNormalTransferAsync, [modeswitch_in_pipe], modeswitch_bos_buf, \
36, modeswitch_inq_data_callback, 0, 1
test eax, eax
jz .fail
ret
.fail:
mov dword [modeswitch_pipe0], 0 ; transaction over
ret
endp
; The INQUIRY data arrived: read the CSW.
proc modeswitch_inq_data_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch INQUIRY data done, status %d len %d\n', [.status], [.length]
invoke USBNormalTransferAsync, [modeswitch_in_pipe], modeswitch_csw, \
13, modeswitch_inq_csw_callback, 0, 1
test eax, eax
jz .fail
ret
.fail:
mov dword [modeswitch_pipe0], 0 ; transaction over
ret
endp
; The INQUIRY transaction is complete: now the switch message itself.
proc modeswitch_inq_csw_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch INQUIRY CSW done, status %d\n', [.status]
invoke USBNormalTransferAsync, [modeswitch_out_pipe], [modeswitch_msg], 31, \
modeswitch_callback, 0, 0
DEBUGF 1,'K : modeswitch CBW submitted, handle %x\n', eax
test eax, eax
jz .fail
ret
.fail:
mov dword [modeswitch_pipe0], 0 ; transaction over
ret
endp
; The BOS descriptor has been read. If the device carries an
; MS OS 2.0 platform capability with a nonzero bAltEnumCode, switch it
; the way Windows does: a vendor control request "set alternate
; enumeration". Otherwise fall back to the bulk switch message.
proc modeswitch_bos_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch BOS done, status %d len %d\n', [.status], [.length]
cmp [.status], 0
jne .fallback
mov ecx, [.length]
sub ecx, 8 ; minus the setup packet
cmp ecx, 5
jb .fallback
mov esi, modeswitch_bos_buf
cmp byte [esi+1], 0x0F ; BOS descriptor type
jne .fallback
movzx edx, word [esi+2] ; wTotalLength
cmp edx, ecx
jbe @f
mov edx, ecx ; clamp to what was received
@@:
add edx, esi ; edx = end of BOS data
add esi, 5 ; first device capability
.cap_loop:
lea eax, [esi+3]
cmp eax, edx
ja .fallback ; no more capabilities
movzx ecx, byte [esi] ; bLength
test ecx, ecx
jz .fallback
cmp byte [esi+1], 0x10 ; DEVICE_CAPABILITY
jne .next_cap
cmp byte [esi+2], 0x05 ; PLATFORM capability
jne .next_cap
cmp ecx, 20+8 ; header + GUID + one set info
jb .next_cap
lea eax, [esi+ecx]
cmp eax, edx
ja .fallback ; capability sticks out of BOS
; is it the MS OS 2.0 platform GUID?
push esi edi ecx
add esi, 4
mov edi, msos20_guid
mov ecx, 16
repe cmpsb
pop ecx edi esi
jne .next_cap
; walk the descriptor set info structures, take one with bAltEnumCode
push ecx
sub ecx, 20
shr ecx, 3 ; number of 8-byte set infos
lea eax, [esi+20]
.set_loop:
test ecx, ecx
jz .no_alt_enum
cmp byte [eax+7], 0 ; bAltEnumCode
jne .set_found
add eax, 8
dec ecx
jmp .set_loop
.set_found:
pop ecx
mov cl, [eax+6] ; bMS_VendorCode
mov [modeswitch_alt_setup+1], cl
mov cl, [eax+7] ; bAltEnumCode -> wValue high byte
mov [modeswitch_alt_setup+3], cl
DEBUGF 1,'K : modeswitch: MS OS 2.0 alt enum supported\n'
mov ebx, [.calldata] ; pipe 0
invoke USBControlTransferAsync, ebx, modeswitch_alt_setup, 0, 0, \
modeswitch_alt_callback, ebx, 0
DEBUGF 1,'K : modeswitch SET_ALT_ENUMERATION submit %x\n', eax
test eax, eax
jz .fallback
ret
.no_alt_enum:
pop ecx
jmp .fallback
.next_cap:
add esi, ecx
jmp .cap_loop
.fallback:
DEBUGF 1,'K : modeswitch: no MS OS 2.0, using bulk message\n'
call modeswitch_send_cbw
ret
endp
; SET_ALT_ENUMERATION completed: on success the device re-enumerates
; by itself; if it stalled the request, try the bulk message instead.
proc modeswitch_alt_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch SET_ALT_ENUMERATION done, status %d\n', [.status]
cmp [.status], 0
je .ret
call modeswitch_send_cbw
.ret:
ret
endp
; The mode-switch CBW has completed. Read the CSW status like
; usb_modeswitch does: some firmwares only switch after the host has
; completed the whole Bulk-Only transaction.
proc modeswitch_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch CBW done, status %d\n', [.status]
cmp [.status], 0
jne .done
mov eax, [modeswitch_in_pipe]
test eax, eax
jz .done
invoke USBNormalTransferAsync, eax, modeswitch_csw, 13, \
modeswitch_csw_callback, 0, 1
test eax, eax
jnz .ret
.done:
mov dword [modeswitch_pipe0], 0 ; transaction over
.ret:
ret
endp
; The CSW arrived (or errored); nothing more to do, the device should
; drop off the bus and re-enumerate in its real configuration.
proc modeswitch_csw_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch CSW done, status %d len %d\n', [.status], [.length]
mov dword [modeswitch_pipe0], 0 ; transaction over
ret
endp
; SET_FEATURE(1) completed; the device either resets into its real
; configuration or (newer firmwares) just resets back into Zero-CD,
; which re-triggers the quirk with the next method of the list.
proc modeswitch_sf_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .buffer:dword, .length:dword, .calldata:dword
DEBUGF 1,'K : modeswitch SET_FEATURE done, status %d\n', [.status]
mov dword [modeswitch_pipe0], 0 ; transaction over
ret
endp
proc AddDevice
push ebx esi
virtual at esp
@@ -956,134 +737,6 @@ end virtual
; bInterfaceProtocol are subsequent in interface_descr, just one
; memory reference is used for both.
mov esi, [.interface]
; Some 3G/LTE modems enumerate as a mass-storage-only "Zero-CD" (a
; virtual CD-ROM with Windows drivers) and must be switched to their
; real configuration by a magic vendor SCSI command sent to the bulk
; OUT endpoint (usb_modeswitch's "HuaweiNewMode"; a SET_FEATURE(1)
; only resets these devices back into Zero-CD). Match by VID:PID,
; fire the command and do not bind: the device drops off the bus and
; re-enumerates with a new PID.
mov ebx, [.pipe0]
invoke USBGetParam, ebx, 0 ; 0 = get device descriptor
test eax, eax
jz .no_modeswitch
mov ecx, [eax+8] ; idVendor | idProduct shl 16
mov edx, modeswitch_ids
.modeswitch_scan:
cmp dword [edx], 0
jz .no_modeswitch
cmp ecx, [edx]
jz .do_modeswitch
add edx, 8
jmp .modeswitch_scan
.do_modeswitch:
; one switch transaction at a time: some Zero-CDs (12d1:14ad) carry TWO
; storage interfaces and AddDevice fires for each; a second concurrent
; CBW confuses the firmware
cmp [modeswitch_pipe0], ebx
je .nothing
; pick the method: repeated appearances of the same id walk its method
; list (wrapping around), a different id starts from the first method
cmp ecx, [modeswitch_last_id]
je @f
mov [modeswitch_last_id], ecx
mov dword [modeswitch_attempt], 0
jmp .method_select
@@:
inc [modeswitch_attempt]
.method_select:
mov eax, [edx+4] ; start of the method list
mov ecx, [modeswitch_attempt]
.method_walk:
cmp dword [eax], -1 ; end of list: wrap around
jne @f
mov eax, [edx+4]
@@:
test ecx, ecx
jz .method_found
add eax, 8
dec ecx
jmp .method_walk
.method_found:
mov [modeswitch_pipe0], ebx
push esi
mov esi, switchdevice
invoke SysMsgBoardStr
pop esi
DEBUGF 1,'K : modeswitch attempt %d, method %d\n', [modeswitch_attempt], [eax]
cmp dword [eax], MSW_SET_FEATURE
je .method_set_feature
xor ecx, ecx
cmp dword [eax], MSW_CBW_INQ
jne @f
inc ecx
@@:
mov [modeswitch_inq], ecx
mov eax, [eax+4] ; the CBW for this attempt
mov [modeswitch_msg], eax
jmp .method_cbw
; SET_FEATURE(1) needs no endpoints: fire the control request and let
; the device drop off the bus by itself
.method_set_feature:
invoke USBControlTransferAsync, ebx, modeswitch_sf_setup, 0, 0, \
modeswitch_sf_callback, 0, 0
DEBUGF 1,'K : modeswitch SET_FEATURE submit %x\n', eax
test eax, eax
jnz .nothing
mov dword [modeswitch_pipe0], 0
jmp .nothing
.method_cbw:
; collect the bulk IN and bulk OUT endpoints of this interface
mov dword [modeswitch_in_pipe], 0
mov dword [modeswitch_in_ep], 0
mov dword [modeswitch_out_ep], 0
mov edx, [.config]
movzx ecx, [edx+config_descr.wTotalLength]
add edx, ecx ; edx = end of configuration data
.modeswitch_ep_scan:
movzx ecx, byte [esi] ; bLength
test ecx, ecx
jz .modeswitch_send ; malformed, use what we have
add esi, ecx
lea ecx, [esi+sizeof.endpoint_descr]
cmp ecx, edx
ja .modeswitch_send ; ran out of descriptors
cmp byte [esi+1], ENDPOINT_DESCR_TYPE
jne .modeswitch_ep_scan
mov cl, [esi+endpoint_descr.bmAttributes]
and cl, 3
cmp cl, BULK_PIPE
jne .modeswitch_ep_scan
movzx ecx, [esi+endpoint_descr.bEndpointAddress]
push edx
movzx edx, [esi+endpoint_descr.wMaxPacketSize]
and edx, 0xFFF
test cl, 80h
jz .modeswitch_ep_out
mov [modeswitch_in_ep], ecx
mov [modeswitch_in_mps], edx
pop edx
jmp .modeswitch_ep_scan
.modeswitch_ep_out:
mov [modeswitch_out_ep], ecx
mov [modeswitch_out_mps], edx
pop edx
jmp .modeswitch_ep_scan
.modeswitch_send:
cmp dword [modeswitch_out_ep], 0
jz .nothing ; no bulk OUT: cannot switch
mov [modeswitch_pipe0], ebx
; try the Windows mechanism first (MS OS 2.0 alternate enumeration,
; this is how E3372h switches); its callback falls back to the classic
; bulk switch message if the device has no such capability
invoke USBControlTransferAsync, ebx, modeswitch_bos_setup, \
modeswitch_bos_buf, 256, modeswitch_bos_callback, ebx, 1
DEBUGF 1,'K : modeswitch BOS read submit %x\n', eax
test eax, eax
jnz .nothing
call modeswitch_send_cbw ; could not even ask: fall back
jmp .nothing
.no_modeswitch:
xor ebx, ebx
mov cx, word [esi+interface_descr.bInterfaceSubClass]
; 1b. For Mass-storage SCSI-command-set Bulk-only devices subclass must be 6
@@ -1338,16 +991,6 @@ proc inquiry_callback
test al, al
jnz .nothing
DEBUGF 1,'K : direct-access mass storage device detected\n'
; Units that report 'medium not present' (the empty card slot of an LTE
; modem or card reader) are not registered: the kernel has no media
; change detection, so such a disk would only sit dead in the file
; managers. Replugging the device after inserting a card registers it.
mov edx, [esp+8]
cmp [edx+usb_unit_data.MediaPresent], 0
jnz @f
DEBUGF 1,'K : no media, not registering the disk\n'
ret 8
@@:
; 3. We have found a new disk device. Increment number of references.
lock inc [ecx+usb_device_data.NumReferences]
; Unfortunately, we are now in the context of the USB thread,
@@ -1754,14 +1397,8 @@ proc disk_read_write stdcall uses ebx esi edi, \
mov eax, [numsectors]
mov eax, [eax]
; 2. The transfer length for SCSI_{READ,WRITE}10 commands can not be greater
; than 0xFFFF sectors, but that is not the practical limit: the field size is
; the only thing the standard bounds, while real sticks hang their firmware on
; multi-megabyte single commands. The kernel disk cache asks for as much as
; CACHE_MAX_ALLOC_SIZE (4 MB) in one call, i.e. 8192 sectors, and that is
; exactly where such sticks stop answering and re-enumerate. Linux caps
; usb-storage at 240 sectors (120 KB) for the same reason; do the same and
; split larger requests into slices.
max_sectors_at_time = 240
; than 0xFFFF, so split the request to slices with <= 0xFFFF sectors.
max_sectors_at_time = 0xFFFF
.split:
push eax ; .length_rest
cmp eax, max_sectors_at_time
@@ -1931,117 +1568,6 @@ inquiry_fail db 'K : INQUIRY command failed',13,10,0
;read_capacity_fail db 'K : READ CAPACITY command failed',13,10,0
;read_fail db 'K : READ command failed',13,10,0
noindex db 'K : failed to generate disk name',13,10,0
switchdevice db 'K : Zero-CD modem detected, switching mode',13,10,0
; Zero-CD devices to switch: pairs of (idVendor + idProduct shl 16,
; pointer to a method list). Different firmware generations accept
; different switch methods and silently ignore (or merely ACK) the
; others, and some do not react to the method the usb_modeswitch
; database prescribes. So every id gets a LIST of methods and each
; (re)appearance of the same id tries the next one, wrapping around.
; No timers needed: an unswitched stick resets itself about half a
; minute after a swallowed command (observed on K3806), and the user
; can always just replug.
MSW_CBW = 0 ; method: bulk message, param = CBW ptr
MSW_SET_FEATURE = 1 ; method: SET_FEATURE(1) control request
MSW_CBW_INQ = 2 ; method: INQUIRY exchange, then the CBW;
; some firmwares accept the switch only
; after normal SCSI traffic (on Linux and
; Windows the storage driver reads the
; virtual CD before any switch tool runs)
align 4
modeswitch_ids dd 0x1F0112D1, modeswitch_list_1f01 ; Huawei E3372 etc
dd 0x14AD12D1, modeswitch_list_14ad ; Vodafone K3806
dd 0
; E3372h-153: the 10-byte command is the only one this firmware
; reacts to (verified on hardware; SET_FEATURE only resets it)
modeswitch_list_1f01:
dd MSW_CBW, modeswitch_cbw_new
dd -1
; K3806: the plain usb_modeswitch message (classic Huawei), the eject
; and the E3372 message are all ACKed but ignored, SET_FEATURE stalls
; (verified on hardware) - so lead with INQUIRY+message
modeswitch_list_14ad:
dd MSW_CBW_INQ, modeswitch_cbw_old
dd MSW_SET_FEATURE, 0
dd MSW_CBW, modeswitch_cbw_eject
dd MSW_CBW, modeswitch_cbw_new
dd MSW_CBW, modeswitch_cbw_old
dd -1
; usb_modeswitch's message for the 1F01 Zero-CD family: a CBW with the
; 10-byte vendor command 11 06 20 00 00 00 00 00 01 00 (note the 01 in
; byte 8; the older 6-byte 11 06 20 00 00 01 variant is ignored by
; E3372h firmwares) and no data stage
modeswitch_cbw_new:
db 'USBC' ; dCBWSignature
dd 0x12345678 ; dCBWTag
dd 0 ; dCBWDataTransferLength
db 0 ; bmCBWFlags
db 0 ; bCBWLUN
db 10 ; bCBWCBLength
db 0x11, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
db 0, 0, 0, 0, 0, 0
; the classic Huawei message for older sticks (usb_modeswitch 12d1:14ad
; etc): the 6-byte vendor command 11 06 20 00 00 01, byte-for-byte as
; usb_modeswitch sends it (bCBWCBLength is 0 in the original message)
modeswitch_cbw_old:
db 'USBC' ; dCBWSignature
dd 0x12345678 ; dCBWTag
dd 0 ; dCBWDataTransferLength
db 0 ; bmCBWFlags
db 0 ; bCBWLUN
db 0 ; bCBWCBLength
db 0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
db 0, 0, 0, 0, 0, 0
; the standard eject (START STOP UNIT with LoEj|Stop): the generic
; Zero-CD switch used by many non-Huawei sticks
modeswitch_cbw_eject:
db 'USBC' ; dCBWSignature
dd 0x12345678 ; dCBWTag
dd 0 ; dCBWDataTransferLength
db 0 ; bmCBWFlags
db 0 ; bCBWLUN
db 6 ; bCBWCBLength
db 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
db 0, 0, 0, 0, 0, 0
; SET_FEATURE(1) to the device: the switch of the oldest Huawei sticks
modeswitch_sf_setup db 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
; standard INQUIRY (36 bytes of data IN), the warm-up for MSW_CBW_INQ
modeswitch_cbw_inq:
db 'USBC' ; dCBWSignature
dd 0x12345678 ; dCBWTag
dd 36 ; dCBWDataTransferLength
db 0x80 ; bmCBWFlags: data IN
db 0 ; bCBWLUN
db 6 ; bCBWCBLength
db 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00
db 0, 0, 0, 0, 0, 0
; scratch state of the mode-switch transaction
modeswitch_pipe0 dd 0 ; config pipe of the device
; (nonzero = transaction running)
modeswitch_msg dd 0 ; the CBW chosen for this device
modeswitch_inq dd 0 ; run an INQUIRY before the CBW
modeswitch_out_pipe dd 0 ; bulk OUT pipe handle
modeswitch_last_id dd 0 ; VID:PID of the last attempt
modeswitch_attempt dd 0 ; method index for that id
modeswitch_in_pipe dd 0 ; bulk IN pipe handle (for the CSW)
modeswitch_in_ep dd 0
modeswitch_in_mps dd 0
modeswitch_out_ep dd 0
modeswitch_out_mps dd 0
; GET_DESCRIPTOR(BOS), up to 256 bytes
modeswitch_bos_setup db 0x80, 0x06, 0x00, 0x0F, 0x00, 0x00
dw 256
; MS OS 2.0 "set alternate enumeration": vendor request to the device,
; bRequest (+1) and wValue high byte (+3) are patched in at runtime
modeswitch_alt_setup db 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
; platform capability GUID of MS OS 2.0: D8DD60DF-4589-4CC7-9CD2-659D9E648A9F
msos20_guid db 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C
db 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F
modeswitch_csw rb 16 ; CSW receive buffer
modeswitch_bos_buf rb 256 ; BOS descriptor buffer
align 4
; Structure with callback functions.
-3
View File
@@ -1,3 +0,0 @@
if tup.getconfig("NO_FASM") ~= "" then return end
ROOT = "../../.."
tup.rule("xhci.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
File diff suppressed because it is too large. Load diff
-993
View File
@@ -1,993 +0,0 @@
; Device slots, contexts and pipes for the xHCI driver.
; This file is included from xhci.asm.
; =============================================================================
; ============================ Context helpers ================================
; =============================================================================
; Returns the address of one context inside a context structure.
; in: eax = base of the structure, ecx = index of the context,
; esi -> usb_controller.
; out: eax = address of the context.
proc xhci_context
push ecx edx
mov edx, [esi+xhci_controller.ContextSize-XCD]
imul edx, ecx
add eax, edx
pop edx ecx
ret
endp
; Zeroes the Input Context. The caller must hold CmdLock.
; in: esi -> usb_controller.
proc xhci_clear_input_ctx
push eax ecx edi
mov edi, [esi+xhci_controller.InputCtx-XCD]
xor eax, eax
mov ecx, 33*64/4
rep stosd
pop edi ecx eax
ret
endp
; Returns the pipe of the default control endpoint of the same device, which
; represents the device as a whole.
; in: ebx -> xhci_pipe. out: eax -> xhci_pipe or 0.
proc xhci_ctrl_pipe
mov eax, [ebx+xhci_pipe.DevPage]
test eax, eax
jz .nothing
mov eax, [eax+XHCI_PIPES_OFS+1*4]
test eax, eax
jz .nothing
sub eax, sizeof.xhci_pipe
.nothing:
ret
endp
; Fills the Slot Context of the Input Context from the device description kept
; in a pipe. The caller must hold CmdLock.
; in: esi -> usb_controller, ebx -> xhci_pipe describing the device,
; ecx = value for the Context Entries field.
proc xhci_fill_slot_ctx
push eax ecx edx edi
mov eax, [esi+xhci_controller.InputCtx-XCD]
push ecx
movi ecx, 1
call xhci_context
pop ecx
mov edi, eax
; dword 0: Route String, Speed and Context Entries.
mov eax, [ebx+xhci_pipe.Route]
and eax, 0FFFFFh
if XHCI_SUPERSPEED
; A SuperSpeed root-port device carries the raw PORTSC speed identifier;
; its kernel-visible Speed pretends high-speed and must not get here.
mov edx, [ebx+xhci_pipe.PSIV]
test edx, edx
jnz .havespeed
end if
mov edx, [ebx+xhci_pipe.Speed]
cmp edx, USB_SPEED_FS
jz .fs
cmp edx, USB_SPEED_LS
jz .ls
movi edx, XHCI_PSI_HS
jmp .havespeed
.fs:
movi edx, XHCI_PSI_FS
jmp .havespeed
.ls:
movi edx, XHCI_PSI_LS
.havespeed:
shl edx, 20
or eax, edx
shl ecx, 27
or eax, ecx
mov [edi], eax
; dword 1: Root Hub Port Number.
mov eax, [ebx+xhci_pipe.RootPort]
shl eax, 16
mov [edi+4], eax
; dword 2: the Transaction Translator, if the device is served by one.
mov eax, [ebx+xhci_pipe.TTSlot]
test eax, eax
jz @f
mov edx, [ebx+xhci_pipe.TTPort]
shl edx, 8
or eax, edx
@@:
mov [edi+8], eax
and dword [edi+12], 0
pop edi edx ecx eax
ret
endp
; Fills the Endpoint Context of the Input Context for the given pipe.
; The caller must hold CmdLock.
; in: esi -> usb_controller, ebx -> xhci_pipe.
proc xhci_fill_ep_ctx
push eax ecx edx edi
mov eax, [esi+xhci_controller.InputCtx-XCD]
mov ecx, [ebx+xhci_pipe.DCI]
inc ecx
call xhci_context
mov edi, eax
; dword 0: Interval.
mov eax, [ebx+xhci_pipe.Interval]
shl eax, 16
mov [edi], eax
; dword 1: Error Count, Endpoint Type, Max Burst Size and Max Packet Size.
mov eax, [ebx+xhci_pipe.EpType]
shl eax, 3
or eax, 3 shl 1 ; three retries before giving up
mov edx, [ebx+xhci_pipe.MaxPacket]
mov ecx, edx
shr ecx, 11
and ecx, 3 ; extra transactions per microframe
shl ecx, 8
or eax, ecx
if XHCI_SUPERSPEED
; A SuperSpeed bulk endpoint may allow bursts of several packets; the field
; shares its bits with the extra-transactions ones, which are zero then.
mov ecx, [ebx+xhci_pipe.MaxBurst]
shl ecx, 8
or eax, ecx
end if
and edx, 7FFh
shl edx, 16
or eax, edx
mov [edi+4], eax
; dwords 2 and 3: the TR Dequeue Pointer with the Dequeue Cycle State.
mov eax, [ebx+xhci_pipe.Enqueue]
shl eax, 4
add eax, [ebx+xhci_pipe.RingPhys]
or eax, [ebx+xhci_pipe.Cycle]
mov [edi+8], eax
and dword [edi+12], 0
; dword 4: Average TRB Length, only a hint for the bandwidth scheduler.
mov eax, [ebx+xhci_pipe.MaxPacket]
and eax, 7FFh
cmp [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
jnz @f
movi eax, 8
@@:
mov [edi+16], eax
and dword [edi+20], 0
pop edi edx ecx eax
ret
endp
; =============================================================================
; ============================== Slot commands ================================
; =============================================================================
; Issues the Address Device command for a newly created default control pipe.
; in: esi -> usb_controller, ebx -> xhci_pipe. out: eax = 0 on failure.
proc xhci_address_device
push ebx ecx edx edi
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexLock
call xhci_clear_input_ctx
mov edx, [esi+xhci_controller.InputCtx-XCD]
mov dword [edx+4], 3 ; add the Slot Context and endpoint zero
movi ecx, 1
call xhci_fill_slot_ctx
call xhci_fill_ep_ctx
mov [ebx+xhci_pipe.MaxDCI], 1
; Point the DCBAA entry of the slot at the Device Context.
mov eax, [esi+xhci_controller.CommonPage-XCD]
mov ecx, [ebx+xhci_pipe.SlotId]
mov edx, [ebx+xhci_pipe.DevPagePhys]
mov [eax+ecx*8], edx
and dword [eax+ecx*8+4], 0
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, XHCI_TRB_ADDRESS_DEV shl 10
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
push ebx
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_submit
pop ebx
push eax
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexUnlock
pop eax
cmp eax, XHCI_CC_SUCCESS
jz .ok
DEBUGF 1,'K : XHCI: Address Device failed, code %d\n',eax
xor eax, eax
jmp .nothing
.ok:
movi eax, 1
.nothing:
pop edi edx ecx ebx
ret
endp
; Issues a Configure Endpoint command that adds the given endpoint.
; in: esi -> usb_controller, ebx -> xhci_pipe of the endpoint,
; edi -> xhci_pipe of the default control endpoint of the same device.
; out: eax = completion code.
proc xhci_configure_endpoint
push ebx ecx edx esi edi
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexLock
call xhci_clear_input_ctx
; Drop the endpoint and add it again, so that reopening an endpoint that has
; been closed before also works.
mov ecx, [ebx+xhci_pipe.DCI]
movi eax, 1
shl eax, cl
mov edx, [esi+xhci_controller.InputCtx-XCD]
mov [edx], eax
or eax, 1 ; the Slot Context is always added
mov [edx+4], eax
call xhci_fill_ep_ctx
; The Context Entries field must cover every endpoint in use by the device.
mov ecx, [ebx+xhci_pipe.DCI]
cmp ecx, [edi+xhci_pipe.MaxDCI]
jae @f
mov ecx, [edi+xhci_pipe.MaxDCI]
@@:
mov [edi+xhci_pipe.MaxDCI], ecx
push ebx
mov ebx, edi
call xhci_fill_slot_ctx
pop ebx
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, XHCI_TRB_CONFIG_EP shl 10
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
push ebx
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_submit
pop ebx
push eax
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexUnlock
pop eax
pop edi esi edx ecx ebx
ret
endp
; Tells the controller where the endpoint has to continue from.
; in: esi -> usb_controller, ebx -> xhci_pipe.
proc xhci_set_dequeue
pushad
cmp [ebx+xhci_pipe.SlotId], 0
jz .nothing
mov eax, [ebx+xhci_pipe.Dequeue]
shl eax, 4
add eax, [ebx+xhci_pipe.RingPhys]
or eax, [ebx+xhci_pipe.Cycle]
mov ecx, [ebx+xhci_pipe.DCI]
shl ecx, 16
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, ecx
or edx, XHCI_TRB_SET_DEQ shl 10
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_sync
cmp eax, XHCI_CC_SUCCESS
jz .nothing
DEBUGF 1,'K : XHCI: Set TR Dequeue Pointer failed, code %d\n',eax
.nothing:
popad
ret
endp
; =============================================================================
; =============================== New device ==================================
; =============================================================================
; Called from xhci_port_init and from the hub support code when a new device
; has been connected and reset. Enables a device slot for it and hands it over
; to the protocol layer.
; in: esi -> usb_controller, eax = speed. out: eax = 0 on failure.
proc xhci_new_device
push ebx ecx edx edi
mov [esi+usb_controller.ResettingSpeed], al
; 1. Reserve room for the pseudo-pipe that describes the new device. Only the
; fields read by xhci_init_pipe are filled in; the layout matches a real pipe,
; so the result can be passed to usb_new_device as a usb_pipe pointer.
sub esp, sizeof.xhci_pipe + 4
mov ebx, esp
push ebx
mov edi, ebx
xor eax, eax
mov ecx, (sizeof.xhci_pipe + 4)/4
rep stosd
pop ebx
mov [ebx+sizeof.xhci_pipe], esi ; usb_pipe.Controller
movzx eax, [esi+usb_controller.ResettingSpeed]
mov [ebx+xhci_pipe.Speed], eax
; 2. Compute the root hub port, the route string and the tier of the device.
movzx edx, [esi+usb_controller.ResettingPort]
mov edi, [esi+usb_controller.ResettingHub]
test edi, edi
jnz .behind_hub
mov eax, [esi+xhci_controller.PortMap-XCD+edx*4]
mov [ebx+xhci_pipe.RootPort], eax
if XHCI_SUPERSPEED
mov eax, [esi+xhci_controller.ResettingPSIV-XCD]
mov [ebx+xhci_pipe.PSIV], eax
end if
jmp .have_topology
.behind_hub:
; The parent hub is a device too, and its own pipe carries the topology data.
mov eax, [edi+USB_HUB_CONFIGPIPE]
sub eax, sizeof.xhci_pipe
mov ecx, [eax+xhci_pipe.RootPort]
mov [ebx+xhci_pipe.RootPort], ecx
mov ecx, [eax+xhci_pipe.Depth]
mov eax, [eax+xhci_pipe.Route]
; The route string holds one nibble per tier, at most five of them.
cmp ecx, 5
jae .have_route
push ecx edx
shl ecx, 2
inc edx ; the route uses 1-based port numbers
cmp edx, 15
jbe @f
movi edx, 15
@@:
shl edx, cl
or eax, edx
pop edx ecx
.have_route:
inc ecx
mov [ebx+xhci_pipe.Depth], ecx
mov [ebx+xhci_pipe.Route], eax
; 3. Low- and full-speed devices behind a high-speed hub need the address of
; the Transaction Translator that serves them.
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
jz .have_topology
push ebx
mov ecx, edx
mov edx, edi
invoke usbhc_api.usb_get_tt
pop ebx
test edx, edx
jz .have_topology
sub edx, sizeof.xhci_pipe
mov eax, [edx+xhci_pipe.SlotId]
mov [ebx+xhci_pipe.TTSlot], eax
inc ecx
mov [ebx+xhci_pipe.TTPort], ecx
.have_topology:
; 4. Ask the controller for a device slot.
xor eax, eax
push ebx
xor ebx, ebx
xor ecx, ecx
mov edx, XHCI_TRB_ENABLE_SLOT shl 10
call xhci_cmd_sync
pop ebx
cmp eax, XHCI_CC_SUCCESS
jnz .fail
test edx, edx
jz .fail
mov [ebx+xhci_pipe.SlotId], edx
DEBUGF 1,'K : XHCI new device: slot %d, root port %d, route %x, speed %d\n',edx,[ebx+xhci_pipe.RootPort],[ebx+xhci_pipe.Route],[ebx+xhci_pipe.Speed]
; 5. Hand the device over to the protocol layer. It opens the pipe of the
; default control endpoint, and that is where the slot is really addressed.
lea ecx, [ebx+sizeof.xhci_pipe]
invoke usbhc_api.usb_new_device
test eax, eax
jnz .done
; 6. The protocol layer has failed; release the slot again.
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, XHCI_TRB_DISABLE_SLOT shl 10
xor eax, eax
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_sync
xor eax, eax
jmp .done
.fail:
dbgstr 'XHCI: Enable Slot failed'
xor eax, eax
.done:
add esp, sizeof.xhci_pipe + 4
pop edi edx ecx ebx
ret
endp
; =============================================================================
; ================================= Pipes =====================================
; =============================================================================
proc xhci_alloc_pipe
push ebx ecx edi
mov ebx, xhci_ep_mutex
invoke usbhc_api.usb_allocate_common, sizeof.xhci_pipe + sizeof.usb_pipe
test eax, eax
jz @f
; Zero the whole block: the kernel may call FreePipe for a pipe whose InitPipe
; has never run, and that path must not act on garbage.
mov edi, eax
push eax
xor eax, eax
movi ecx, (sizeof.xhci_pipe + sizeof.usb_pipe + 3)/4
rep stosd
pop eax
add eax, sizeof.xhci_pipe
@@:
pop edi ecx ebx
ret
endp
proc xhci_free_pipe stdcall, ptr:dword
push ebx esi edi
mov ebx, [ptr]
sub ebx, sizeof.xhci_pipe
mov esi, [ebx+sizeof.xhci_pipe+usb_pipe.Controller]
test esi, esi
jz .free
cmp [ebx+xhci_pipe.SlotId], 0
jz .drop_pipe
cmp [ebx+xhci_pipe.DCI], 1
jnz .drop_pipe
; This is the default control endpoint, that is, the handle of the whole
; device: release the slot together with the per-device page.
mov ecx, [ebx+xhci_pipe.SlotId]
mov edx, ecx
shl edx, 24
or edx, XHCI_TRB_DISABLE_SLOT shl 10
xor eax, eax
push ebx
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_sync
pop ebx
; The controller may access the Device Context until the command above
; completes, so only now may the DCBAA entry and the slot table forget it.
mov ecx, [ebx+xhci_pipe.SlotId]
mov edi, [esi+xhci_controller.CommonPage-XCD]
and dword [edi+ecx*8], 0
and dword [edi+ecx*8+4], 0
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
mov eax, [ebx+xhci_pipe.DevPage]
test eax, eax
jz .drop_ring
invoke KernelFree, eax
and [ebx+xhci_pipe.DevPage], 0
jmp .drop_ring
.drop_pipe:
; Remove the pipe from the per-device table, if it is still listed there.
; On disconnect the kernel releases the pipes of a device in arbitrary order,
; and the pipe of the default control endpoint - the owner of the per-device
; page - may well be freed before this one, taking the page with it. The
; authoritative pointer is the one in SlotPages: it is cleared when the slot
; is released, so it can never point to freed memory.
mov ecx, [ebx+xhci_pipe.SlotId]
test ecx, ecx
jz .drop_ring
mov eax, [esi+xhci_controller.SlotPages-XCD+ecx*4]
test eax, eax
jz .drop_ring
mov ecx, [ebx+xhci_pipe.DCI]
cmp ecx, 32
jae .drop_ring
and dword [eax+XHCI_PIPES_OFS+ecx*4], 0
.drop_ring:
mov eax, [ebx+xhci_pipe.Ring]
test eax, eax
jz @f
invoke KernelFree, eax
and [ebx+xhci_pipe.Ring], 0
@@:
mov eax, [ebx+xhci_pipe.RingMap]
test eax, eax
jz .free
invoke KernelFree, eax
and [ebx+xhci_pipe.RingMap], 0
.free:
pop edi esi ebx
mov eax, [ptr]
sub eax, sizeof.xhci_pipe
invoke usbhc_api.usb_free_common, eax
ret
endp
; Allocates the transfer ring of a pipe.
; in: ebx -> xhci_pipe. out: eax = 0 on failure.
proc xhci_alloc_ring
push ecx edx
call xhci_alloc_page
test eax, eax
jz .nothing
mov [ebx+xhci_pipe.RingMap], eax
call xhci_alloc_page
test eax, eax
jnz @f
invoke KernelFree, [ebx+xhci_pipe.RingMap]
and [ebx+xhci_pipe.RingMap], 0
xor eax, eax
jmp .nothing
@@:
mov [ebx+xhci_pipe.Ring], eax
mov [ebx+xhci_pipe.RingPhys], edx
; The last entry returns to the beginning of the ring and toggles the cycle.
lea ecx, [eax+(XHCI_RING_TRBS-1)*16]
mov [ecx], edx
mov dword [ecx+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
and [ebx+xhci_pipe.Enqueue], 0
and [ebx+xhci_pipe.Dequeue], 0
and [ebx+xhci_pipe.Reserved], 0
and [ebx+xhci_pipe.FirstFix], 0
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
movi eax, 1
.nothing:
pop edx ecx
ret
endp
; Stores the pipe in the per-device table used by the event ring handler.
; in: ebx -> xhci_pipe.
proc xhci_register_pipe
push eax ecx edx
mov eax, [ebx+xhci_pipe.DevPage]
test eax, eax
jz @f
mov ecx, [ebx+xhci_pipe.DCI]
cmp ecx, 32
jae @f
lea edx, [ebx+sizeof.xhci_pipe]
mov [eax+XHCI_PIPES_OFS+ecx*4], edx
@@:
pop edx ecx eax
ret
endp
; Computes the Interval field of the Endpoint Context of an interrupt endpoint.
; The kernel passes bInterval from the endpoint descriptor: for high-speed
; devices it is an exponent of 125 us periods, for low- and full-speed devices
; it is a number of frames.
; in: ebx -> xhci_pipe, eax = bInterval.
proc xhci_calc_interval
push eax ecx
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
jnz .low_speed
test eax, eax
jz @f
dec eax
@@:
jmp .clamp
.low_speed:
; One frame equals eight periods of 125 us, hence the offset of three.
test eax, eax
jnz @f
movi eax, 1
@@:
bsr ecx, eax
lea eax, [ecx+3]
.clamp:
cmp eax, 15
jbe @f
movi eax, 15
@@:
mov [ebx+xhci_pipe.Interval], eax
pop ecx eax
ret
endp
; Called from usb_open_pipe.
; in: edi -> usb_pipe for the target, ecx -> usb_pipe of the config pipe,
; esi -> usb_controller, eax -> usb_gtd of the first descriptor,
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type,
; [ebp+24] = interval.
; out: eax = 0 on failure.
proc xhci_init_pipe
virtual at ebp+8
.config_pipe dd ?
.endpoint dd ?
.maxpacket dd ?
.type dd ?
.interval dd ?
end virtual
push ebx
sub edi, sizeof.xhci_pipe
sub ecx, sizeof.xhci_pipe
mov ebx, edi ; ebx -> xhci_pipe being initialized
; 1. Copy the description of the device from the config pipe.
mov eax, [ecx+xhci_pipe.SlotId]
mov [ebx+xhci_pipe.SlotId], eax
mov eax, [ecx+xhci_pipe.DevPage]
mov [ebx+xhci_pipe.DevPage], eax
mov eax, [ecx+xhci_pipe.DevPagePhys]
mov [ebx+xhci_pipe.DevPagePhys], eax
mov eax, [ecx+xhci_pipe.Speed]
mov [ebx+xhci_pipe.Speed], eax
mov eax, [ecx+xhci_pipe.RootPort]
mov [ebx+xhci_pipe.RootPort], eax
mov eax, [ecx+xhci_pipe.Route]
mov [ebx+xhci_pipe.Route], eax
mov eax, [ecx+xhci_pipe.Depth]
mov [ebx+xhci_pipe.Depth], eax
mov eax, [ecx+xhci_pipe.TTSlot]
mov [ebx+xhci_pipe.TTSlot], eax
mov eax, [ecx+xhci_pipe.TTPort]
mov [ebx+xhci_pipe.TTPort], eax
if XHCI_SUPERSPEED
mov eax, [ecx+xhci_pipe.PSIV]
mov [ebx+xhci_pipe.PSIV], eax
end if
; 2. Work out the Device Context Index and the endpoint type.
mov eax, [.endpoint]
test eax, eax
jz .control_ep
mov ecx, eax
and ecx, 15
add ecx, ecx
test al, 80h
jz @f
inc ecx
or [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
@@:
mov [ebx+xhci_pipe.DCI], ecx
mov eax, [.type]
cmp eax, BULK_PIPE
jz .bulk
cmp eax, INTERRUPT_PIPE
jz .interrupt
; A control endpoint other than endpoint zero is unusual but legal.
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
jmp .have_type
.bulk:
movi eax, XHCI_EP_BULK_OUT
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
jz @f
movi eax, XHCI_EP_BULK_IN
@@:
mov [ebx+xhci_pipe.EpType], eax
jmp .have_type
.interrupt:
movi eax, XHCI_EP_INT_OUT
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
jz @f
movi eax, XHCI_EP_INT_IN
@@:
mov [ebx+xhci_pipe.EpType], eax
mov eax, [.interval]
call xhci_calc_interval
.have_type:
mov eax, [.maxpacket]
mov [ebx+xhci_pipe.MaxPacket], eax
if XHCI_SUPERSPEED
call xhci_ss_get_burst
end if
jmp .alloc_ring
.control_ep:
; The default control endpoint always has index one. Until the real packet size
; is known from the device descriptor, use the value the specification requires
; for the speed of the device: the kernel asks for 64 regardless of the speed,
; which is wrong for low- and full-speed devices.
mov [ebx+xhci_pipe.DCI], 1
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
movi eax, 64
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
jz @f
movi eax, 8
@@:
if XHCI_SUPERSPEED
; A SuperSpeed device always uses 512 bytes on the default control endpoint.
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
jb @f
mov eax, 512
@@:
end if
mov [ebx+xhci_pipe.MaxPacket], eax
.alloc_ring:
; 3. Allocate the transfer ring.
call xhci_alloc_ring
test eax, eax
jz .fail
; 4. Choose the software list the pipe belongs to and insert it there. The
; hardware knows nothing about these lists; they exist only so that the kernel
; can walk all pipes and reinsert an aborted one.
lea edx, [esi+xhci_controller.ControlED-XCD]
cmp [.type], BULK_PIPE
jb @f
lea edx, [esi+xhci_controller.BulkED-XCD]
jz @f
lea edx, [esi+xhci_controller.IntED-XCD]
@@:
lea edi, [ebx+sizeof.xhci_pipe]
mov [edi+usb_pipe.BaseList], edx
mov ecx, [edx+usb_pipe.NextVirt]
mov [edi+usb_pipe.NextVirt], ecx
mov [edi+usb_pipe.PrevVirt], edx
mov [ecx+usb_pipe.PrevVirt], edi
mov [edx+usb_pipe.NextVirt], edi
; 5. Now do the hardware part.
cmp [.endpoint], 0
jz .address_device
call xhci_register_pipe
mov edi, [.config_pipe]
sub edi, sizeof.xhci_pipe
call xhci_configure_endpoint
xhci_trace 'K : XHCI open pipe: slot %d dci %d\n', [ebx+xhci_pipe.SlotId], [ebx+xhci_pipe.DCI]
cmp eax, XHCI_CC_SUCCESS
jz .success
DEBUGF 1,'K : XHCI: Configure Endpoint failed, code %d\n',eax
jmp .unlink_fail
.address_device:
; 6. This is a new device: allocate its Device Context, publish the slot and
; let the controller give the device a bus address.
call xhci_alloc_page
test eax, eax
jz .unlink_fail
mov [ebx+xhci_pipe.DevPage], eax
mov [ebx+xhci_pipe.DevPagePhys], edx
mov ecx, [ebx+xhci_pipe.SlotId]
mov [esi+xhci_controller.SlotPages-XCD+ecx*4], eax
call xhci_register_pipe
call xhci_address_device
test eax, eax
jz .free_devpage
.success:
; usb_open_pipe keeps the pointer to the new pipe in edi across this call, so
; it has to be handed back untouched; the branch above has overwritten it with
; the pipe of the default control endpoint.
lea edi, [ebx+sizeof.xhci_pipe]
pop ebx
movi eax, 1
ret
.free_devpage:
mov ecx, [ebx+xhci_pipe.SlotId]
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
mov eax, [ebx+xhci_pipe.DevPage]
invoke KernelFree, eax
and [ebx+xhci_pipe.DevPage], 0
.unlink_fail:
; Undo the insertion into the software list before failing.
lea edi, [ebx+sizeof.xhci_pipe]
mov eax, [edi+usb_pipe.NextVirt]
mov edx, [edi+usb_pipe.PrevVirt]
mov [eax+usb_pipe.PrevVirt], edx
mov [edx+usb_pipe.NextVirt], eax
.fail:
lea edi, [ebx+sizeof.xhci_pipe]
pop ebx
xor eax, eax
ret
endp
; Removes the pipe from the hardware configuration of the device.
; in: esi -> usb_controller, ebx -> usb_pipe.
proc xhci_unlink_pipe
pushad
sub ebx, sizeof.xhci_pipe
cmp [ebx+xhci_pipe.SlotId], 0
jz .nothing
cmp [ebx+xhci_pipe.DCI], 1
jz .nothing ; the slot itself is released by FreePipe
call xhci_ctrl_pipe
test eax, eax
jz .nothing
mov edi, eax ; edi -> pipe of endpoint zero
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexLock
call xhci_clear_input_ctx
mov ecx, [ebx+xhci_pipe.DCI]
movi eax, 1
shl eax, cl
mov edx, [esi+xhci_controller.InputCtx-XCD]
mov [edx], eax ; drop this endpoint
mov dword [edx+4], 1 ; keep the Slot Context
mov ecx, [edi+xhci_pipe.MaxDCI]
test ecx, ecx
jnz @f
movi ecx, 1
@@:
push ebx
mov ebx, edi
call xhci_fill_slot_ctx
pop ebx
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, XHCI_TRB_CONFIG_EP shl 10
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_submit
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexUnlock
.nothing:
popad
ret
endp
; Temporarily removes the pipe from the hardware schedule.
; in: esi -> usb_controller, ebx -> usb_pipe.
proc xhci_disable_pipe
pushad
sub ebx, sizeof.xhci_pipe
cmp [ebx+xhci_pipe.SlotId], 0
jz .nothing
mov ecx, [ebx+xhci_pipe.DCI]
shl ecx, 16
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, ecx
or edx, XHCI_TRB_STOP_EP shl 10
xor eax, eax
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_sync
.nothing:
popad
ret
endp
; Reinserts the pipe into the hardware schedule after xhci_disable_pipe, with
; an empty transfer queue.
; in: esi -> usb_controller, ebx -> usb_pipe,
; edx -> current descriptor, eax -> new last descriptor.
proc xhci_enable_pipe
pushad
sub ebx, sizeof.xhci_pipe
mov eax, [ebx+xhci_pipe.Ring]
test eax, eax
jz .nothing
; The queue is empty now, so the ring can be restarted from its beginning.
mov edi, eax
xor eax, eax
mov ecx, 0x1000/4
rep stosd
mov edi, [ebx+xhci_pipe.RingMap]
mov ecx, 0x1000/4
rep stosd
mov edi, [ebx+xhci_pipe.Ring]
add edi, (XHCI_RING_TRBS-1)*16
mov eax, [ebx+xhci_pipe.RingPhys]
mov [edi], eax
mov dword [edi+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
and [ebx+xhci_pipe.Enqueue], 0
and [ebx+xhci_pipe.Dequeue], 0
and [ebx+xhci_pipe.Reserved], 0
and [ebx+xhci_pipe.FirstFix], 0
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
call xhci_set_dequeue
.nothing:
popad
ret
endp
; =============================================================================
; ========================== Address and packet size ==========================
; =============================================================================
; Called from usb_set_address_callback. The bus address is chosen by the
; controller itself while executing the Address Device command, so the only
; thing left to do is to remember the number the kernel has reserved: it asks
; for it back on disconnect in order to mark it free again.
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address.
proc xhci_set_device_address
movzx eax, cl
mov [ebx+xhci_pipe.Address-sizeof.xhci_pipe], eax
jmp [usbhc_api.usb_subscribe_control]
endp
; in: esi -> usb_controller, ebx -> usb_pipe. out: eax = address.
proc xhci_get_device_address
mov eax, [ebx+xhci_pipe.Address-sizeof.xhci_pipe]
ret
endp
; Called from usb_get_descr8_callback once the real packet size of the default
; control endpoint is known. On xHCI that value lives in the Endpoint Context,
; so an Evaluate Context command is needed to update it.
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size.
proc xhci_set_endpoint_packet_size
push ebx ecx edx edi
sub ebx, sizeof.xhci_pipe
if XHCI_SUPERSPEED
; For a SuperSpeed device bMaxPacketSize0 is an exponent, and the only value
; the specification allows is 9: use 512 directly instead of the raw byte.
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
jb @f
mov ecx, 512
@@:
end if
mov [ebx+xhci_pipe.MaxPacket], ecx
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexLock
call xhci_clear_input_ctx
mov edx, [esi+xhci_controller.InputCtx-XCD]
mov dword [edx+4], 2 ; evaluate the default control endpoint
call xhci_fill_ep_ctx
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, XHCI_TRB_EVAL_CTX shl 10
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
push ebx
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_submit
pop ebx
cmp eax, XHCI_CC_SUCCESS
jz @f
DEBUGF 1,'K : XHCI: Evaluate Context failed, code %d\n',eax
@@:
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexUnlock
pop edi edx ecx ebx
jmp [usbhc_api.usb_subscribe_control]
endp
; If the descriptor that has just completed is the answer to a request for the
; hub descriptor, tell the controller that the device is a hub: it has to know
; that in order to serve the devices behind it.
; in: ebx -> usb_gtd.
proc xhci_check_hub_descriptor
pushad
cmp [ebx+usb_gtd.Callback], 0
jz .nothing
mov eax, [ebx+usb_gtd.Pipe]
mov esi, [eax+usb_pipe.Controller]
sub eax, sizeof.xhci_pipe
test [eax+xhci_pipe.Flags], XHCI_PIPE_HUBPEND
jz .nothing
and [eax+xhci_pipe.Flags], not XHCI_PIPE_HUBPEND
cmp [ebx+xhci_gtd.Status-sizeof.xhci_gtd], XHCI_CC_SUCCESS
jnz .nothing
mov edx, [eax+xhci_pipe.HubBuf]
test edx, edx
jz .nothing
cmp byte [edx+1], 29h ; bDescriptorType
jnz .nothing
or [eax+xhci_pipe.Flags], XHCI_PIPE_ISHUB
mov ebx, eax ; ebx -> xhci_pipe of the hub
movzx edi, byte [edx+2] ; bNbrPorts
movzx ebp, byte [edx+3] ; low byte of wHubCharacteristics
shr ebp, 5
and ebp, 3 ; Transaction Translator Think Time
DEBUGF 1,'K : XHCI: device on slot %d is a hub with %d ports\n',[ebx+xhci_pipe.SlotId],edi
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexLock
call xhci_clear_input_ctx
mov eax, [esi+xhci_controller.InputCtx-XCD]
mov dword [eax+4], 1 ; only the Slot Context is evaluated
mov ecx, [ebx+xhci_pipe.MaxDCI]
test ecx, ecx
jnz @f
movi ecx, 1
@@:
call xhci_fill_slot_ctx
; Patch the Slot Context with the fields that describe a hub. Only Configure
; Endpoint takes them into account, Evaluate Context would ignore them.
mov eax, [esi+xhci_controller.InputCtx-XCD]
movi ecx, 1
call xhci_context
or dword [eax], 1 shl 26 ; this device is a hub
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
jnz @f
shl ebp, 16
or [eax+8], ebp
@@:
shl edi, 24
or [eax+4], edi ; Number of Ports
mov edx, [ebx+xhci_pipe.SlotId]
shl edx, 24
or edx, XHCI_TRB_CONFIG_EP shl 10
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
xor ebx, ebx
xor ecx, ecx
call xhci_cmd_submit
cmp eax, XHCI_CC_SUCCESS
jz @f
DEBUGF 1,'K : XHCI: cannot mark the device as a hub, code %d\n',eax
@@:
lea ecx, [esi+xhci_controller.CmdLock-XCD]
invoke MutexUnlock
.nothing:
popad
ret
endp
-135
View File
@@ -1,135 +0,0 @@
; SuperSpeed support for the xHCI driver, included from xhci.asm when
; XHCI_SUPERSPEED is enabled. The pieces too small to live here - the port
; map, the Slot Context speed, the 512-byte default control endpoint, the
; Max Burst field of the Endpoint Context - sit in the other files under
; "if XHCI_SUPERSPEED" guards; this file keeps the self-contained procedures.
;
; The kernel USB stack knows nothing about SuperSpeed, so it never learns
; about it: a SuperSpeed device is announced as a high-speed one, which also
; keeps the Transaction Translator logic away from it. The raw PORTSC speed
; identifier travels in xhci_pipe.PSIV instead and reaches everything that
; really needs it. SuperSpeed hubs are not supported: the kernel only speaks
; the USB2 hub protocol, so a device behind a USB3 hub is served by the USB2
; half of that hub at high speed.
; =============================================================================
; ============================ SuperSpeed ports ===============================
; =============================================================================
; Called from xhci_new_port for a SuperSpeed root port instead of the USB2
; reset entry point: a SuperSpeed link trains itself and the port enables
; itself on connect, reporting the speed with no reset at all. When the link
; is already up, skip straight to the reset recovery stage, after which
; xhci_port_init picks the device up; otherwise try a warm reset.
; in: esi -> usb_controller, ecx = port index.
proc xhci_ss_start_port
push eax edx
and [esi+usb_controller.ResettingHub], 0
mov [esi+usb_controller.ResettingPort], cl
push ecx
invoke GetTimerTicks
pop ecx
mov [esi+usb_controller.ResetTime], eax
mov [esi+xhci_controller.ResetStart-XCD], eax
call xhci_port_reg
mov eax, [edx]
test al, XHCI_PORT_PED
jz .warm_reset
mov [esi+usb_controller.ResettingStatus], 2
DEBUGF 1,'K : XHCI %x: SS port %d link is up, PORTSC=%x\n',esi,ecx,eax
jmp .nothing
.warm_reset:
; Connected, but the link has not come up. The Port Reset bit is set while a
; warm reset is running, so the ordinary reset-wait machinery in
; xhci_port_reset_done serves this case unchanged; the extra WRC change bit is
; acknowledged there together with the usual ones.
mov dword [edx], XHCI_PORT_PP + XHCI_PORT_WPR
mov [esi+usb_controller.ResettingStatus], 1
DEBUGF 1,'K : XHCI %x: warm-resetting port %d, PORTSC=%x\n',esi,ecx,eax
.nothing:
pop edx eax
ret
endp
; The kernel restarts pending root ports through the NewPortReset entry of
; usb_hardware_func directly, bypassing xhci_new_port; SuperSpeed ports must
; not get the USB2 reset on that path either, so the entry points here.
; in: esi -> usb_controller, ecx = port index.
proc xhci_ss_port_reset
bt [esi+xhci_controller.SSPortMask-XCD], ecx
jnc xhci_new_port.reset
call xhci_ss_start_port
ret
endp
; =============================================================================
; ===================== Endpoint Companion descriptors ========================
; =============================================================================
; Reads the SuperSpeed Endpoint Companion descriptor of a bulk endpoint and
; keeps its bMaxBurst for the Endpoint Context, allowing bursts of up to
; bMaxBurst+1 packets per transaction. Zero (no bursts) is always legal, so
; any failure just leaves the field alone. Only bulk endpoints are considered:
; a nonzero burst on a periodic endpoint would also require the Max ESIT
; Payload fields, and real interrupt endpoints do not burst anyway.
; Relies on the stack frame of usb_open_pipe exactly like xhci_init_pipe does:
; [ebp+8] is the config pipe of the device.
; in: ebx -> xhci_pipe of a non-control endpoint being opened.
proc xhci_ss_get_burst
push eax ecx edx edi
; 1. Only SuperSpeed bulk endpoints are of interest.
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
jb .nothing
mov eax, [ebx+xhci_pipe.EpType]
and al, 3
cmp al, 2 ; bulk endpoint types are 2 and 6
jnz .nothing
; 2. Find the configuration data kept by the kernel behind the device
; descriptor; it holds the endpoint descriptors with their companions.
mov eax, [ebp+8]
mov eax, [eax+usb_pipe.DeviceData]
test eax, eax
jz .nothing
movzx edx, [eax+usb_device_data.DeviceDescrSize]
mov edi, [eax+usb_device_data.ConfigDataSize]
lea ecx, [eax+edx+usb_device_data.DeviceDescriptor]
add edi, ecx ; edi -> end of the configuration data
; 3. Reconstruct bEndpointAddress from the Device Context Index.
mov edx, [ebx+xhci_pipe.DCI]
shr edx, 1
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
jz @f
or dl, 80h
@@:
; 4. Walk the descriptors to the one of this endpoint.
.walk:
lea eax, [ecx+2]
cmp eax, edi
ja .nothing
movzx eax, byte [ecx] ; bLength
test eax, eax
jz .nothing ; malformed data, stop
cmp byte [ecx+1], 5 ; an endpoint descriptor?
jnz .advance
cmp [ecx+2], dl ; bEndpointAddress
jnz .advance
; 5. The companion descriptor (type 30h) immediately follows its endpoint.
add ecx, eax
lea eax, [ecx+3]
cmp eax, edi
ja .nothing
cmp byte [ecx+1], 30h ; SuperSpeed Endpoint Companion
jnz .nothing
movzx eax, byte [ecx+2] ; bMaxBurst
cmp eax, 15
ja .nothing
mov [ebx+xhci_pipe.MaxBurst], eax
DEBUGF 1,'K : XHCI: slot %d dci %d bursts %d+1 packets\n',[ebx+xhci_pipe.SlotId],[ebx+xhci_pipe.DCI],eax
jmp .nothing
.advance:
add ecx, eax
jmp .walk
.nothing:
pop edi edx ecx eax
ret
endp
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+3 -15
View File
@@ -1489,31 +1489,19 @@ dyndisk_handler:
; 12. The fs operation has specified some partition.
push edx ecx
xor eax, eax
mov ecx, eax
lodsb
@@:
lea ecx, [ecx*4 + ecx]
shl ecx, 1
sub eax, '0'
jb .dyndisk_cleanup
jz .dyndisk_cleanup
cmp eax, 10
jnc .dyndisk_cleanup
add ecx, eax
cmp ecx, MAX_NUM_PARTITIONS
ja .dyndisk_cleanup
mov ecx, eax
lodsb
cmp eax, '/'
jz @f
test eax, eax
jnz @b
jnz .dyndisk_cleanup
dec esi
@@:
test ecx, ecx
jz .dyndisk_cleanup
cmp byte [esi], 0
jnz @f
; partition info
+16 -76
View File
@@ -2507,7 +2507,7 @@ dword-значение цвета 0x00RRGGBB
* иначе eax = TID - идентификатор потока
---------------------- Константы для регистров: ----------------------
eax - SF_THREAD_CONTROL (51) /
eax - SF_CREATE_THREAD (51) /
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
@@ -4098,9 +4098,6 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* подфункция 7 - запуск программы
* подфункция 8 - удаление файла/папки
* подфункция 9 - создание папки
* подфункция 10 - переименование/перемещение
* подфункция 11 - создание симлинка
* подфункция 12 - чтение симлинка
Для CD-приводов в связи с аппаратными ограничениями доступны
только подфункции 0,1,5 и 7, вызов других подфункций завершится
ошибкой с кодом 2.
@@ -4115,8 +4112,7 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
SSF_READ_SYMLINK (12)
SSF_CREATE_FOLDER (9)
======================================================================
= Функция 70, подфункция 0 - чтение файла с поддержкой длинных имён. =
======================================================================
@@ -4468,62 +4464,6 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* Формирование нового пути отличается от общих правил:
относительный путь относится к папке целевого файла (или папки),
абсолютный путь считается от корня раздела.
---------------------- Константы для регистров: ----------------------
eax - SF_FILE (70)
[ebx] - SSF_RENAME (10)
======================================================================
=========== Функция 70, подфункция 11 - создание симлинка. ===========
======================================================================
Параметры:
* eax = 70 - номер функции
* ebx = указатель на информационную структуру
Формат информационной структуры:
* +0: dword: 11 = номер подфункции
* +4: dword: 0 (зарезервировано)
* +8: dword: 0 (зарезервировано)
* +12 = +0xC: dword: 0 (зарезервировано)
* +16 = +0x10: dword: указатель на строку с целевым путём
* +20 = +0x14: путь, правила формирования имён указаны в общем
описании (путь ссылки)
Возвращаемое значение:
* eax = 0 - успешно, иначе код ошибки файловой системы
* ebx разрушается
Замечания:
* Родительская папка должна существовать.
* Для CD функция не поддерживается (возвращает код ошибки 2).
---------------------- Константы для регистров: ----------------------
eax - SF_FILE (70)
[ebx] - SSF_CREATE_SYMLINK (11)
======================================================================
============ Функция 70, подфункция 12 - чтение симлинка. ============
======================================================================
Параметры:
* eax = 70 - номер функции
* ebx = указатель на информационную структуру
Формат информационной структуры:
* +0: dword: 12 = номер подфункции
* +4: dword: 0 (зарезервировано)
* +8: dword: 0 (зарезервировано)
* +12 = +0xC: dword: размер буфера в байтах
* +16 = +0x10: dword: указатель на буфер для целевого пути
* +20 = +0x14: путь, правила формирования имён указаны в общем
описании (путь ссылки)
Возвращаемое значение:
* eax = 0 - успешно, иначе код ошибки файловой системы
* ebx = число байт, записанных в буфер
Замечания:
* Функция не следует по симлинку; она читает целевой путь,
на который указывает симлинк.
* Целевой путь всегда завершается нулём, в том числе при обрезании;
записывается не более (размер буфера - 1) байт пути.
* Значение в ebx включает завершающий 0, как в подфункции 2
функции 30.
---------------------- Константы для регистров: ----------------------
eax - SF_FILE (70)
[ebx] - SSF_READ_SYMLINK (12)
======================================================================
========== Функция 71 - установить заголовок окна программы ==========
======================================================================
@@ -5119,8 +5059,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* eax = дескриптор фьютекса, 0 при ошибке
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_CREATE (0)
eax - SF_FUTEX (77)
ebx - SSF_CREATE (0)
======================================================================
============= Функция 77, подфункция 1, Удалить фьютекс. =============
======================================================================
@@ -5134,8 +5074,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* Ядро автоматически удаляет фьютексы при завершении процесса.
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_DESTROY (1)
eax - SF_FUTEX (77)
ebx - SSF_DESTROY (1)
======================================================================
================= Функция 77, подфункция 2, Ожидать. =================
======================================================================
@@ -5151,8 +5091,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
-2 - контрольное значение фьютекса не соответствует
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_WAIT (2)
eax - SF_FUTEX (77)
ebx - SSF_WAIT (2)
======================================================================
================ Функция 77, подфункция 3, Разбудить. ================
======================================================================
@@ -5165,8 +5105,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* eax = количество разбуженых
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_WAKE (3)
eax - SF_FUTEX (77)
ebx - SSF_WAKE (3)
======================================================================
Замечания:
* Подфункции 4-7 зарезервированы и сейчас возвращают -1.
@@ -5188,8 +5128,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* Поддерживаются только pipe-дескрипторы.
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FD_READ (10)
eax - SF_FUTEX (77)
ebx - SSF_FILE_READ (10)
======================================================================
======== Функция 77, подфункция 11, Записать из буфера в файл. =======
@@ -5208,8 +5148,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
* Поддерживаются только pipe-дескрипторы.
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FD_WRITE (11)
eax - SF_FUTEX (77)
ebx - SSF_FILE_WRITE (11)
======================================================================
=========== Функция 77, подфункция 13, Создать новый pipe. ===========
@@ -5233,8 +5173,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
- дескриптором записи.
---------------------- Константы для регистров: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FD_PIPE2 (13)
eax - SF_FUTEX (77)
ebx - SSF_PIPE_CREATE (13)
======================================================================
========== Функция -1 - завершить выполнение потока/процесса =========
+16 -74
View File
@@ -2492,7 +2492,7 @@ Returned value:
* otherwise eax = TID - thread identifier
---------------------- Constants for registers: ----------------------
eax - SF_THREAD_CONTROL (51)
eax - SF_CREATE_THREAD (51)
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
======================================================================
@@ -4060,9 +4060,6 @@ Available subfunctions:
* subfunction 7 - start application
* subfunction 8 - delete file/folder
* subfunction 9 - create folder
* subfunction 10 - rename/move
* subfunction 11 - create symlink
* subfunction 12 - read symlink
For CD-drives due to hardware limitations only subfunctions
0,1,5 and 7 are available, other subfunctions return error
with code 2.
@@ -4076,8 +4073,7 @@ is called for corresponding device.
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
SSF_READ_SYMLINK (12)
SSF_CREATE_FOLDER (9)
======================================================================
=== Function 70, subfunction 0 - read file with long names support. ==
======================================================================
@@ -4427,60 +4423,6 @@ Remarks:
* New path forming differs from general rules:
relative path relates to the target's parent folder,
absolute path relates to the partition's root folder.
---------------------- Constants for registers: ----------------------
eax - SF_FILE (70)
[ebx] - SSF_RENAME (10)
======================================================================
=========== Function 70, subfunction 11 - create symlink. ============
======================================================================
Parameters:
* eax = 70 - function number
* ebx = pointer to the information structure
Format of the information structure:
* +0: dword: 11 = subfunction number
* +4: dword: 0 (reserved)
* +8: dword: 0 (reserved)
* +12 = +0xC: dword: 0 (reserved)
* +16 = +0x10: dword: pointer to the target path string
* +20 = +0x14: path, general rules of names forming (link path)
Returned value:
* eax = 0 - success, otherwise file system error code
* ebx destroyed
Remarks:
* The parent folder must already exist.
* The function is not supported for CD (returns error code 2).
---------------------- Constants for registers: ----------------------
eax - SF_FILE (70)
[ebx] - SSF_CREATE_SYMLINK (11)
======================================================================
============ Function 70, subfunction 12 - read symlink. =============
======================================================================
Parameters:
* eax = 70 - function number
* ebx = pointer to the information structure
Format of the information structure:
* +0: dword: 12 = subfunction number
* +4: dword: 0 (reserved)
* +8: dword: 0 (reserved)
* +12 = +0xC: dword: buffer size in bytes
* +16 = +0x10: dword: pointer to buffer for target path
* +20 = +0x14: path, general rules of names forming (link path)
Returned value:
* eax = 0 - success, otherwise file system error code
* ebx = number of bytes written to the buffer
Remarks:
* The function does not follow the symlink; it reads the target path
that the symlink points to.
* The target path is always terminated with 0, even when truncated;
at most (buffer size - 1) path bytes are written.
* The value returned in ebx includes the terminating 0, as in
subfunction 2 of function 30.
---------------------- Constants for registers: ----------------------
eax - SF_FILE (70)
[ebx] - SSF_READ_SYMLINK (12)
======================================================================
================== Function 71 - set window caption ==================
======================================================================
@@ -5331,8 +5273,8 @@ Returned value:
* eax = futex handle, 0 on error
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_CREATE (0)
eax - SF_FUTEX (77)
ebx - SSF_CREATE (0)
======================================================================
========= Function 77, Subfunction 1, Destroy futex object ===========
======================================================================
@@ -5347,8 +5289,8 @@ Remarks:
terminates.
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_DESTROY (1)
eax - SF_FUTEX (77)
ebx - SSF_DESTROY (1)
======================================================================
=============== Function 77, Subfunction 2, Futex wait ===============
======================================================================
@@ -5364,8 +5306,8 @@ Returned value:
-2 - futex control value doesn't match
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_WAIT (2)
eax - SF_FUTEX (77)
ebx - SSF_WAIT (2)
======================================================================
=============== Function 77, Subfunction 3, Futex wake ===============
======================================================================
@@ -5378,8 +5320,8 @@ Returned value:
* eax = number of waiters that were woken up
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FUTEX_WAKE (3)
eax - SF_FUTEX (77)
ebx - SSF_WAKE (3)
======================================================================
Remarks:
* Subfunctions 4-7 are reserved and currently return -1.
@@ -5401,8 +5343,8 @@ Remarks:
* Only pipe descriptors are supported.
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FD_READ (10)
eax - SF_FUTEX (77)
ebx - SSF_FILE_READ (10)
======================================================================
=========== Function 77, Subfunction 11, Write to file. =============
======================================================================
@@ -5420,8 +5362,8 @@ Remarks:
* Only pipe descriptors are supported.
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FD_WRITE (11)
eax - SF_FUTEX (77)
ebx - SSF_FILE_WRITE (11)
======================================================================
========== Function 77, Subfunction 13, Create pipe. ================
======================================================================
@@ -5439,8 +5381,8 @@ Remarks:
write handle.
---------------------- Constants for registers: ----------------------
eax - SF_POSIX (77)
ebx - SSF_FD_PIPE2 (13)
eax - SF_FUTEX (77)
ebx - SSF_PIPE_CREATE (13)
======================================================================
=== Function 80 - file system interface with parameter of encoding ===
======================================================================
+72 -1035
View File
File diff suppressed because it is too large. Load diff
+1 -2
View File
@@ -2405,12 +2405,11 @@ fat_Write:
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
; First two cases are fatal errors, in third case we may write some data
cmp al, ERROR_DISK_FULL
jnz .noWrite
jnz @f
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
.noWrite:
push 0
.ret:
pop eax eax eax ecx ecx
+1 -13
View File
@@ -182,20 +182,8 @@ proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
.case6:
cmp dword [ebx], 6
jnz .case11
mov ecx, 32
jmp .end_switch
.case11:
cmp dword [ebx], 11
jnz .case12
stdcall is_string_userspace, edx
jmp .ret
.case12:
cmp dword [ebx], 12
jnz .switch_none
mov ecx, dword [ebx + 12]
mov ecx, 32
jmp .end_switch
.switch_none:
+1 -2
View File
@@ -253,10 +253,9 @@ UTF16to8_string:
UTF16to8:
; in:
; ax = UTF-16 char
; eax = UTF-16 char
; edi -> buffer for UTF-8 char (increasing)
; ecx = byte counter (decreasing)
movzx eax, ax
dec ecx
js .ret
cmp eax, 80h
-6
View File
@@ -48,10 +48,6 @@ dtext:
add esp, 28
ret
.nomem:
add esp, 40
ret
.redirect:
mov ebp, [edi]
add edi, 8
@@ -85,8 +81,6 @@ dtext:
mov [esp+32], eax
imul ebp, eax
stdcall kernel_alloc, ebp
test eax, eax
jz .nomem
mov ecx, ebp
shr ecx, 2
mov [esp+36], eax
+6 -53
View File
@@ -1,6 +1,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv4.INC ;;
@@ -765,9 +765,9 @@ ipv4_output_raw:
push ebx ; push the mac
push ax
inc [IPv4_packets_tx + edi]
inc [IPv4_packets_tx + 4*edi]
mov ax, ETHER_PROTO_IPv4
mov ebx, [net_device_list + edi]
mov ebx, [net_device_list + 4*edi]
mov ecx, [esp + 6 + 4]
add ecx, sizeof.IPv4_header
mov edx, esp
@@ -951,7 +951,7 @@ endp
; edi = device number*4 ;
; ;
; DESTROYED: ;
; ebx, ecx ;
; ecx ;
; ;
;-----------------------------------------------------------------;
align 4
@@ -964,7 +964,6 @@ ipv4_route:
cmp eax, 0xffffffff
je .broadcast
; Check for on-link
xor edi, edi
.loop:
mov ebx, [IPv4_address + edi]
@@ -979,55 +978,9 @@ ipv4_route:
cmp edi, 4*NET_DEVICES_MAX
jb .loop
; no on-link match, find first device with a gateway
mov edi, 4 ; skip loopback device
.loop_gw:
cmp [IPv4_gateway + edi], 0
jne .found_gw
add edi, 4
cmp edi, 4*NET_DEVICES_MAX
jb .loop_gw
jmp .loopback ; no gateway found, fall-back to loopback device
.found_gw:
mov eax, [IPv4_gateway + edi]
jmp .got_it
mov eax, [IPv4_gateway + 4] ; TODO: let user (or a user space daemon) configure default route
.broadcast:
; broadcast: we will do our best without full routing..
; find the first non loopback device which has an active link without IP address
mov edi, 4 ; skip loopback device
.bc_loop1:
mov ebx, [net_device_list + edi]
test ebx, ebx
jz @f
cmp [ebx + NET_DEVICE.link_state], 0
je @f
cmp [IPv4_address + edi], 0
je .got_it
@@:
add edi, 4
cmp edi, 4*NET_DEVICES_MAX
jb .bc_loop1
; If there is no such device, try the one with active link and IP address
mov edi, 4 ; skip loopback device
.bc_loop2:
mov ebx, [net_device_list + edi]
test ebx, ebx
jz @f
cmp [ebx + NET_DEVICE.link_state], 0
jne .got_it
@@:
add edi, 4
cmp edi, 4*NET_DEVICES_MAX
jb .bc_loop2
; jmp .loopback ; no gateway found, fall-back to loopback device
.loopback:
xor edi, edi ; nowhere to go for now.. route it to the loopback device
mov edi, 4 ; TODO: same as above
.got_it:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
test edx, edx
+12 -2
View File
@@ -142,6 +142,7 @@ struct TCP_SOCKET IP_SOCKET
ts_val dd ?
seg_next dd ? ; re-assembly queue
seg_count dd ? ; number of segments queued in it
ends
@@ -780,6 +781,8 @@ socket_close:
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne .free
test [eax + SOCKET.state], SS_ISCONNECTED
jz @f
test [eax + SOCKET.state], SS_ISDISCONNECTING
jnz @f
call tcp_disconnect
@@ -2124,12 +2127,19 @@ socket_free:
mov ebx, eax
cmp [eax + STREAM_SOCKET.rcv.start_ptr], 0
je @f
stdcall kernel_free, [eax + STREAM_SOCKET.rcv.start_ptr]
stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
@@:
cmp [ebx + STREAM_SOCKET.snd.start_ptr], 0
je @f
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
@@:
; free the TCP out-of-order reassembly queue, if any
.free_reasm:
cmp [ebx + TCP_SOCKET.seg_next], 0
je .reasm_done
call tcp_reasm_free_head
jmp .free_reasm
.reasm_done:
mov eax, ebx
.no_stream:
+2 -1
View File
@@ -118,7 +118,7 @@ SS_MORETOCOME = 0x4000
SS_BLOCKED = 0x8000
SOCKET_BUFFER_SIZE = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
SOCKET_BUFFER_SIZE = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
MAX_backlog = 20 ; maximum backlog for stream sockets
; Error Codes
@@ -167,6 +167,7 @@ NET_HWACC_TCP_IPv4_OUT = 1 shl 1
; Network frame types
NET_BUFF_LOOPBACK = 0
NET_BUFF_ETH = 1
NET_BUFF_TCP_REASM = 2 ; held in a TCP reassembly queue, offset/length = TCP payload
struct NET_DEVICE
+12
View File
@@ -99,6 +99,17 @@ TCP_QUEUE_SIZE = 50
TCP_ISSINCR = 128000
; A NET_BUFF queued for reassembly (TCP_SOCKET.seg_next): offset/length = TCP payload
struct TCP_reasm_buff NET_BUFF
Seq dd ? ; sequence number of the first payload byte
Flags dd ? ; TH_FIN if the segment carried a FIN
ends
TCP_reasm_maxsegs = 64 ; max queued segments per socket
TCP_reasm_maxbuffs = NET_BUFFERS / 4 ; max queued segments, all sockets together
struct TCP_header
SourcePort dw ?
@@ -137,6 +148,7 @@ align 4
TCP_queue rd (TCP_QUEUE_SIZE*sizeof.TCP_queue_entry + sizeof.queue)/4
TCP_input_event dd ?
TCP_timer1_event dd ?
TCP_reasm_buffs dd ? ; NET_BUFFs held by all reassembly queues
endg
uglobal
+21 -11
View File
@@ -19,6 +19,7 @@ TCP_BIT_NEEDOUTPUT = 1 shl 0
TCP_BIT_TIMESTAMP = 1 shl 1
TCP_BIT_DROPSOCKET = 1 shl 2
TCP_BIT_FIN_IS_ACKED = 1 shl 3
TCP_BIT_BUFF_QUEUED = 1 shl 4 ; the reassembly queue owns the buffer
;-----------------------------------------------------------------;
; ;
@@ -355,14 +356,9 @@ endl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
; remember the peer's scale factor; it is applied to SND_SCALE when the
; connection is established (together with our RCV_SCALE)
lodsb
cmp al, TCP_max_winshift
jbe .wscale_capped
mov al, TCP_max_winshift
.wscale_capped:
mov [ebx + TCP_SOCKET.requested_s_scale], al
mov [ebx + TCP_SOCKET.SND_SCALE], al
;;;;; TODO
@@:
jmp .opt_loop
@@ -932,7 +928,7 @@ endl
pop word[ebx + TCP_SOCKET.SND_SCALE]
@@:
call tcp_reassemble
call tcp_reassemble_drain
mov eax, [edx + TCP_header.SequenceNumber]
dec eax
@@ -1696,16 +1692,22 @@ endl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
[edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
; Uh-oh, some data is out of order, let's call TCP reassemble for help
; The reassembly queue takes over the buffer: edx is invalid from here on
call tcp_reassemble ;;; TODO!
mov esi, [dataoffset]
add esi, edx
mov eax, [esp] ; the NET_BUFF
call tcp_reassemble
or [temp_bits], TCP_BIT_BUFF_QUEUED
; Generate ACK immediately, to let the other end know that a segment was received out of order,
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
jmp .final_processing ;;; HACK because of unimplemented reassembly queue!
test eax, TH_FIN
jnz .process_fin
jmp .final_processing
.data_done:
;-----------------------------------------------------------------------------------
@@ -1716,6 +1718,7 @@ endl
test [edx + TCP_header.Flags], TH_FIN
jz .final_processing
.process_fin: ; must not use edx from here on
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
@@ -1802,11 +1805,18 @@ endl
call tcp_output
.done:
test [temp_bits], TCP_BIT_BUFF_QUEUED
jnz .buff_queued
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
call net_buff_free
jmp .loop
.buff_queued:
add esp, 4 ; the queue has the buffer
jmp .loop
;-----------------------------------------------------------------------------------
;
; Drop segment, reply with an RST segment when needed
+192 -9
View File
@@ -320,12 +320,12 @@ tcp_respond:
stosb
mov eax, SOCKET_BUFFER_SIZE
sub eax, [esi + STREAM_SOCKET.rcv.size]
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
shr eax, cl ; scale first, then clamp to the
cmp eax, TCP_max_win ; 16-bit field maximum
cmp eax, TCP_max_win
jbe .lessthanmax
mov eax, TCP_max_win
.lessthanmax:
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
shr eax, cl
xchg al, ah
stosw ; window
@@ -488,7 +488,7 @@ tcp_set_persist:
; Start/restart persistence timer.
tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
or [eax + TCP_SOCKET.timer_flags], timer_flag_persist
or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
pop ebx
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
@@ -601,17 +601,200 @@ tcp_mss:
;-----------------------------------------------------------------;
; ;
; tcp_reassemble ;
; tcp_reassemble: queue an out-of-order segment, deliver what is ;
; contiguous with RCV_NXT. The queue owns the NET_BUFF from here. ;
; ;
; IN: ebx = socket ptr ;
; edx = segment ptr ;
; IN: eax = NET_BUFF ptr ;
; ebx = socket ptr (locked) ;
; edx = TCP header ptr ;
; esi = ptr to segment data ;
; ecx = segment data length ;
; ;
; OUT: / ;
; OUT: eax = TH_FIN if the FIN is next in sequence, else 0 ;
; other registers preserved ;
; ;
; tcp_reassemble_drain: delivery only ;
; ;
;-----------------------------------------------------------------;
align 4
tcp_reassemble:
;;;;; TODO
pushad
call tcp_reasm_insert
call tcp_reasm_deliver
mov [esp + 28], eax ; eax slot of pushad
popad
ret
align 4
tcp_reassemble_drain:
pushad
call tcp_reasm_deliver
popad
ret
; IN: eax = NET_BUFF, ebx = socket, edx = TCP header, esi = data, ecx = length
align 4
tcp_reasm_insert:
mov edi, eax ; edi = buffer
mov eax, [edx + TCP_header.SequenceNumber]
movzx ebp, [edx + TCP_header.Flags]
and ebp, TH_FIN
test ecx, ecx
jnz @f
test ebp, ebp
jz .drop ; neither data nor FIN
@@:
; trim data below RCV_NXT
mov edx, eax
sub edx, [ebx + TCP_SOCKET.RCV_NXT]
jns .no_head_trim
neg edx
cmp edx, ecx
ja .drop ; complete duplicate
jb @f
test ebp, ebp ; only the FIN is new?
jz .drop
@@:
add esi, edx
add eax, edx ; seq = RCV_NXT now
sub ecx, edx
xor edx, edx
.no_head_trim:
cmp edx, SOCKET_BUFFER_SIZE
ja .drop
; limits do not apply to the segment at RCV_NXT: it drains the queue
test edx, edx
jnz .check_limits
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jae .limits_ok
.check_limits:
cmp [ebx + TCP_SOCKET.seg_count], TCP_reasm_maxsegs
jae .drop
cmp [TCP_reasm_buffs], TCP_reasm_maxbuffs
jae .drop
.limits_ok:
mov [edi + NET_BUFF.type], NET_BUFF_TCP_REASM
mov [edi + NET_BUFF.length], ecx
sub esi, edi
mov [edi + NET_BUFF.offset], esi
mov [edi + TCP_reasm_buff.Seq], eax
mov [edi + TCP_reasm_buff.Flags], ebp
; find the insertion point, esi = link to update
lea esi, [ebx + TCP_SOCKET.seg_next]
.find:
mov edx, [esi] ; edx = successor candidate
test edx, edx
jz .found
mov ebp, [edx + TCP_reasm_buff.Seq]
sub ebp, eax
jg .found ; successor starts past us
mov esi, edx
jmp .find
.found:
; drop the segment if the previous node already covers it
lea ebp, [ebx + TCP_SOCKET.seg_next]
cmp esi, ebp
je .link ; inserting at the head
mov ebp, [esi + TCP_reasm_buff.Seq]
add ebp, [esi + NET_BUFF.length]
sub ebp, eax
sub ebp, ecx ; prev end - our end
js .link
jnz .drop ; covered, and then some
cmp [edi + TCP_reasm_buff.Flags], 0
je .drop ; covered exactly, no FIN to add
.link:
mov [edi + NET_BUFF.NextPtr], edx
mov [esi + NET_BUFF.NextPtr], edi
inc [ebx + TCP_SOCKET.seg_count]
lock inc [TCP_reasm_buffs]
inc [TCPS_rcvoopack]
add [TCPS_rcvoobyte], ecx
ret
.drop:
stdcall net_buff_free, edi
ret
; IN: ebx = socket, OUT: eax = TH_FIN or 0
align 4
tcp_reasm_deliver:
xor ebp, ebp ; 'delivered anything' flag
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb .done
.loop:
mov edx, [ebx + TCP_SOCKET.seg_next]
test edx, edx
jz .done
mov eax, [edx + TCP_reasm_buff.Seq]
sub eax, [ebx + TCP_SOCKET.RCV_NXT]
jg .done ; hole before this node
neg eax ; node bytes below RCV_NXT
mov ecx, [edx + NET_BUFF.length]
sub ecx, eax ; fresh bytes in the node
jg .deliver
jl .unlink ; ends before RCV_NXT
cmp [edx + TCP_reasm_buff.Flags], 0
jne .fin
.unlink:
call tcp_reasm_free_head
jmp .loop
.deliver:
mov esi, [edx + NET_BUFF.offset]
add esi, edx
add esi, eax
lea eax, [ebx + STREAM_SOCKET.rcv]
call socket_ring_write ; -> ecx = bytes stored
test ecx, ecx
jz .done ; receive buffer full
add [ebx + TCP_SOCKET.RCV_NXT], ecx
mov ebp, 1
jmp .loop
.fin:
call tcp_reasm_free_head
cmp [ebx + TCP_SOCKET.seg_next], 0
jne .fin
mov eax, TH_FIN
jmp .notify
.done:
xor eax, eax
.notify:
test ebp, ebp
jz .nothing
push eax
mov eax, ebx
call socket_notify
pop eax
.nothing:
ret
; IN: ebx = socket (locked), OUT: eax destroyed
align 4
tcp_reasm_free_head:
mov eax, [ebx + TCP_SOCKET.seg_next]
push [eax + NET_BUFF.NextPtr]
pop [ebx + TCP_SOCKET.seg_next]
dec [ebx + TCP_SOCKET.seg_count]
lock dec [TCP_reasm_buffs]
stdcall net_buff_free, eax
ret
+4 -4
View File
@@ -111,13 +111,13 @@ proc tcp_timer_640ms
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jae .dont_kill
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
ja .dont_kill
push [eax + SOCKET.NextPtr]
push eax
call tcp_disconnect
pop eax
jmp .check_only
jmp .loop
.dont_kill:
test [eax + SOCKET.options], SO_KEEPALIVE
+9 -9
View File
@@ -125,7 +125,7 @@ SF_STYLE_SETTINGS=48
SSF_SET_FONT_SIZE=12
SF_APM=49
SF_SET_WINDOW_SHAPE=50
SF_THREAD_CONTROL=51
SF_CREATE_THREAD=51
SSF_CREATE_THREAD=1
SSF_GET_CURR_THREAD_SLOT=2
SSF_GET_THREAD_PRIORITY=3
@@ -281,14 +281,14 @@ SF_NETWORK_PROTOCOL=76
SSF_ARP_DEL_ENTRY=50005h
SSF_ARP_SEND_ANNOUNCE=50006h
SSF_ARP_CONFLICTS_COUNT=50007h
SF_POSIX=77
SSF_FUTEX_CREATE=0
SSF_FUTEX_DESTROY=1
SSF_FUTEX_WAIT=2
SSF_FUTEX_WAKE=3
SSF_FD_READ=10
SSF_FD_WRITE=11
SSF_FD_PIPE2=13
SF_FUTEX=77
SSF_CREATE=0
SSF_DESTROY=1
SSF_WAIT=2
SSF_WAKE=3
SSF_FILE_READ=10
SSF_FILE_WRITE=11
SSF_PIPE_CREATE=13
; File system errors:
FSERR_SUCCESS=0
+1 -1
View File
@@ -1111,7 +1111,7 @@ end if
mov dword [edx+8],ebx
mov dword [edx+4],ecx
mov dword [edx],Kolibri_ThreadFinish
mov eax,SF_THREAD_CONTROL
mov eax,SF_CREATE_THREAD
mov ebx,1
mov ecx,@Kolibri@ThreadMain$qpvt1
int 0x40
Submodule programs/cmm deleted from 4678e1605d.
+6
View File
@@ -0,0 +1,6 @@
if tup.getconfig("NO_CMM") ~= "" then return end
if tup.getconfig("LANG") == "ru_RU"
then C_LANG = "LANG_RUS"
else C_LANG = "LANG_ENG" -- this includes default case without config
end
tup.rule("app_plus.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "app_plus.com")
+18
View File
@@ -0,0 +1,18 @@
struct sysdir
{
char name[64];
char path[64];
} sysdir;
:int SetAdditionalSystemDirectory(dword tName, tPath)
{
int i;
strcpy(#sysdir.name, tName);
strcpy(#sysdir.path, tPath);
$mov eax, 30
$mov ebx, 3
ECX = #sysdir;
$int 0x40
}
+162
View File
@@ -0,0 +1,162 @@
#define MEMSIZE 1024*60
#include "..\lib\gui.h"
#include "..\lib\obj\proc_lib.h"
#include "..\lib\patterns\simple_open_dialog.h"
#include "..\lib\patterns\restart_process.h"
#include "added_sysdir.c"
//===================================================//
// //
// DATA //
// //
//===================================================//
#define WINW 570
#define WINH 300
#define CONX 28 //content X pos
#define CONY 25 //content Y pos
char default_dir[] = "/sys";
od_filter filter2;
#define BTN_MANUAL_SEARCH 10
#define BTN_OPEN_ANYWAY 11
#define APP_PLUS_INI_PATH "/sys/settings/app_plus.ini"
//===================================================//
// //
// TRANSLATIONS //
// //
//===================================================//
#ifdef LANG_RUS
?define WINDOW_TITLE_TEXT "Внимание!"
?define CONTENT_HEADER_TEXT "KolibriOS работает в режиме дискеты"
?define DESCRIPTION_TEXT "Многие приложения сейчас недоступны.
Причина в том, что не смонтирован дополнительный системный
каталог. Но вы можете найти и задать его вручную. Его название
'kolibrios'. Вы также можете загрузить latest-dirstr.7z через
WebView и найти его внутри."
?define MANUALLY_BUTTON_TEXT "Указать папку /kolibrios/..."
?define OPEN_ANYWAY_BUTTON_TEXT "Запустить APP+ (некоторые программы будут недоступны)"
#else
?define WINDOW_TITLE_TEXT "Warning!"
?define CONTENT_HEADER_TEXT "KolibriOS is running in floppy mode"
?define DESCRIPTION_TEXT "A lot of apps aren't available.
The reason is that additional system directory is not mounted.
But you can find and set it manually. Its name is 'kolibrios'.
You can also download latest-dirstr.7z via WebView and find
it inside."
?define MANUALLY_BUTTON_TEXT "Choose /kolibrios/ folder..."
?define OPEN_ANYWAY_BUTTON_TEXT "Open APP+ anyway (some programs won't be available)"
#endif
//===================================================//
// //
// CODE //
// //
//===================================================//
void main()
{
if (param) {
SetAdditionalSystemDirectory("kolibrios", #param+1);
ExitProcess();
}
WaitAutosearch();
CheckKosMounted();
o_dialog.type = 2;
#define NO_DLL_INIT
load_dll(Proc_lib, #OpenDialog_init,0);
OpenDialog_init stdcall (#o_dialog);
active_button_id = BTN_MANUAL_SEARCH;
loop() switch(@WaitEvent())
{
case evButton:
EventButton(GetButtonID());
break;
case evKey:
@GetKeyScancode();
if (AL == SCAN_CODE_ENTER) {
EventButton(active_button_id);
} else if (AL == SCAN_CODE_TAB) {
active_button_id = active_button_id-10^1 + 10;
DrawButtons();
}
break;
case evReDraw:
draw_window();
}
}
void draw_window()
{
sc.get();
DefineAndDrawWindow(screen.w-WINW/2, 100, WINW, WINH+skin_h, 0x34, sc.work, WINDOW_TITLE_TEXT,0);
draw_icon_16w(CONX+2, CONY-3, 5);
WriteTextB(CONX+27+2,CONY+2,0x81,MixColors(sc.work, 0xB92234,220),CONTENT_HEADER_TEXT);
WriteTextB(CONX+27,CONY,0x81,0xB92234,CONTENT_HEADER_TEXT);
WriteTextLines(CONX,CONY+42,0x90,sc.work_text,DESCRIPTION_TEXT,20);
DrawButtons();
}
void DrawButtons()
{
DrawStandartCaptButton(CONX, WINH-CONY-58, BTN_MANUAL_SEARCH, MANUALLY_BUTTON_TEXT);
DrawStandartCaptButton(CONX, WINH-CONY-22, BTN_OPEN_ANYWAY, OPEN_ANYWAY_BUTTON_TEXT);
}
void CheckKosMounted()
{
if (dir_exists("/kolibrios"))
{
if (file_exists(APP_PLUS_INI_PATH)) EventOpenApp();
ExitProcess();
}
}
void WaitAutosearch()
{
while (CheckProcessExists("SEARCHAP")) pause(2);
}
//===================================================//
// //
// EVENTS //
// //
//===================================================//
void EventManualSearch()
{
OpenDialog_start stdcall (#o_dialog);
if (o_dialog.status) SetAdditionalSystemDirectory("kolibrios", #openfile_path+1);
pause(3);
CheckKosMounted();
}
void EventOpenApp()
{
if (RunProgram("/sys/syspanel", APP_PLUS_INI_PATH) < 0) {
notify("'App+ cannot start because\n/sys/syspanel does not exist' -E");
}
}
void EventButton(dword id)
{
if (id==CLOSE_BTN) ExitProcess();
else if (id==BTN_MANUAL_SEARCH) EventManualSearch();
else if (id==BTN_OPEN_ANYWAY) {
EventOpenApp();
ExitProcess();
}
}
stop:
+6
View File
@@ -0,0 +1,6 @@
@c-- /D=LANG_ENG app_plus.c
@del *.
@rename *.com *.
@del warning.txt
@pause
+5
View File
@@ -0,0 +1,5 @@
@c-- /D=LANG_RUS app_plus.c
@del *.
@rename *.com *.
@del warning.txt
@pause
+6
View File
@@ -0,0 +1,6 @@
if tup.getconfig("NO_CMM") ~= "" then return end
if tup.getconfig("LANG") == "ru_RU"
then C_LANG = "LANG_RUS"
else C_LANG = "LANG_ENG" -- this includes default case without config
end
tup.rule("appearance.c", "c-- /D=AUTOBUILD /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "appearance.com")
+472
View File
@@ -0,0 +1,472 @@
//11.03.12 - start!
#define MEMSIZE 1024*70
#include "../lib/mem.h"
#include "../lib/strings.h"
#include "../lib/io.h"
#include "../lib/list_box.h"
#include "../lib/gui.h"
#include "../lib/obj/box_lib.h"
#include "../lib/obj/proc_lib.h"
#include "../lib/obj/libini.h"
#include "../lib/patterns/select_list.h"
#include "../lib/patterns/simple_open_dialog.h"
#include "../lib/patterns/restart_process.h"
dword fmas;
#include "ui_elements_preview.h"
#include "const.h"
//===================================================//
// //
// DATA //
// //
//===================================================//
int active_skin=-1, active_wallpaper=-1, active_screensaver=-1;
checkbox optionbox_stretch = { T_CHECKBOX_STRETCH, false };
checkbox optionbox_tiled = { T_CHECKBOX_TILED, false };
checkbox optionbox_auto = { T_CHECKBOX_AUTO, true };
char ss_available[200];
collection list;
//===================================================//
// //
// CODE //
// //
//===================================================//
void main()
{
int id, i;
load_dll(boxlib, #box_lib_init,0);
load_dll(libini, #lib_init,1);
load_dll(Proc_lib, #OpenDialog_init,0);
OpenDialog_init stdcall (#o_dialog);
GetIniSettings();
tabs.add(#t_skins, #EventTabSkinsClick);
tabs.add(#t_wallpapers, #EventTabWallpappersClick);
tabs.add(#t_screensaver, #EventTabScreensaverClick);
tabs.draw_active_tab();
SetEventMask(EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER);
loop() switch(WaitEvent())
{
case evMouse:
SelectList_ProcessMouse();
if (tabs.active_tab == TAB_SCREENSAVERS) {
scrollbar_h_mouse stdcall (#ss_timeout);
if (ss_timeout.redraw) {
draw_timeout();
ss_timeout.redraw = false; //reset flag
}
}
break;
case evButton:
id=GetButtonID();
if (id==1) EventExit();
tabs.click(id);
if (tabs.active_tab == TAB_SKINS) {
checkbox1.click(id);
spinbox1.click(id);
}
if (tabs.active_tab == TAB_WALLPAPERS) {
if (id==BTN_SELECT_WALLP_FOLDER) EventSelectWallpFolder();
if (optionbox_stretch.click(id)) EventSetWallpMode(1,0,0);
if (optionbox_tiled.click(id)) EventSetWallpMode(0,1,0);
if (optionbox_auto.click(id)) EventSetWallpMode(0,0,1);
}
if (tabs.active_tab == TAB_SCREENSAVERS) {
if (id==BTN_TEST_SCREENSAVER) EventOpenFile();
if (id==BTN_SET_SCREENSAVER) EventSetSs();
}
break;
case evKey:
GetKeys();
if (select_list.ProcessKey(key_scancode)) { EventApply(); break; }
if (key_scancode==SCAN_CODE_ENTER) { EventOpenFile(); break; }
if (key_scancode==SCAN_CODE_DEL) { EventDeleteFile(); break; }
if (key_scancode==SCAN_CODE_TAB) {
id = tabs.active_tab+1;
if(id==3)id=0;
tabs.click(id + tabs.base_id);
break;
}
for (i=select_list.cur_y+1; i<select_list.count; i++)
{
id = list.get(i) + strrchr(list.get(i), '/');
if (ESBYTE[id]==key_ascii) || (ESBYTE[id]==key_ascii-32)
{
select_list.cur_y = i - 1;
select_list.KeyDown();
EventApply();
break;
}
}
break;
case evReDraw:
draw_window();
}
}
void draw_window()
{
sc.get();
DefineAndDrawWindow(screen.w-WIN_W-9/2,80,WIN_W+9,WIN_H+4+skin_h,0x74,sc.work,WINDOW_HEADER,0);
DrawBar(0, 0, WIN_W, PANEL_H-2, sc.work); //top
DrawBar(0, PANEL_H-2, LP-2, WIN_H-PANEL_H-LP+4, EDX); //left
DrawBar(LIST_W+LP+20, PANEL_H-2, WIN_W-LIST_W-26, WIN_H-PANEL_H-LP+4, EDX); //right
DrawBar(0, WIN_H-LP+2, WIN_W, LP-2, EDX); //bottom
tabs.draw();
draw_icon_16w(tabs.x + TAB_P, LP+5, 17);
draw_icon_16w(sizeof(t_skins)-1*8 + TAB_P + TAB_P + tabs.x, LP+5, 6);
draw_icon_16w(sizeof(t_wallpapers)+sizeof(t_skins)-2*8 + TAB_P + TAB_P + TAB_P + tabs.x, LP+5, 61);
if (tabs.active_tab == TAB_SKINS)
{
DrawFrame(RIGHTx, PANEL_H+5, RIGHTw, RIGHTh, T_UI_PREVIEW);
DrawUiElementsPreview(RIGHTx+20, PANEL_H+5, RIGHTh);
}
if (tabs.active_tab == TAB_WALLPAPERS)
{
DrawFrame(RIGHTx, PANEL_H+5, 180, 105, T_PICTURE_MODE);
optionbox_stretch.draw(RIGHTx+14, PANEL_H+25);
optionbox_tiled.draw(RIGHTx+14, PANEL_H+52);
optionbox_auto.draw(RIGHTx+14, PANEL_H+79);
DrawStandartCaptButton(RIGHTx, PANEL_H+130, BTN_SELECT_WALLP_FOLDER, T_SELECT_FOLDER);
}
if (tabs.active_tab == TAB_SCREENSAVERS)
{
draw_timeout();
ss_timeout.line_col = sc.line;
ss_timeout.frnt_col = sc.work;
scrollbar_h_draw stdcall (#ss_timeout);
DrawRectangle(RIGHTx, RIGHTy+25, RIGHTw-20, 15, sc.line);
ESI = DrawStandartCaptButton(RIGHTx, PANEL_H + 65, BTN_TEST_SCREENSAVER, T_SS_PREVIEW);
DrawStandartCaptButton(RIGHTx+ESI, PANEL_H + 65, BTN_SET_SCREENSAVER, T_SS_SET);
}
$push select_list.cur_y
SelectList_Init(
LP,
PANEL_H,
LIST_W,
WIN_H - LP - PANEL_H
);
$pop select_list.cur_y
SelectList_Draw();
SelectList_DrawBorder();
}
void draw_timeout()
{
miniprintf(#param, T_SS_TIMEOUT, ss_timeout.position+1);
WriteTextWithBg(RIGHTx, PANEL_H, 0xD0, sc.work_text, #param, sc.work);
}
void add_filesnames_into_the_list()
{
int j;
for (j=0; j<select_list.count; j++) {
miniprintf(#param,"%s/",#folder_path);
strcat(#param, io.dir.position(ESDWORD[j*4+fmas]));
list.add(#param);
}
}
void Open_Dir()
{
int j;
dword ext;
select_list.ClearList();
if (io.dir.buffer) free(io.dir.buffer);
io.dir.load(#folder_path,DIR_ONLYREAL);
if (fmas) free(fmas);
fmas = malloc(io.dir.count * 4);
for (j=0; j<io.dir.count; j++)
{
strncpy(#param, io.dir.position(j), PATHLEN);
strlwr(#param);
ext = #param + strrchr(#param,'.');
if (tabs.active_tab==TAB_SKINS) {
if (!streq(ext,"skn")) continue;
}
if (tabs.active_tab==TAB_WALLPAPERS) {
if (!streq(ext,"png")) && (!streq(ext,"jpg"))
&& (!streq(ext,"jpeg")) && (!streq(ext,"bmp"))
&& (!streq(ext,"gif")) continue;
}
ESDWORD[select_list.count*4 + fmas] = j;
select_list.count++;
}
sort_by_name(0, select_list.count-1);
list.drop();
//save current item for tab change
//add default item
if(tabs.active_tab == TAB_SKINS)
{
select_list.count++;
list.add(#default_skin);
add_filesnames_into_the_list();
if (active_skin==-1) && (ESBYTE[#previous_skin])
{
for (j=0; j<select_list.count; j++) {
if (streq(list.get(j), #previous_skin)) {
active_skin = j;
break;
}
}
}
select_list.cur_y = active_skin;
} else {
select_list.count++;
list.add(#default_wallp);
add_filesnames_into_the_list();
if (active_wallpaper==-1) && (ESBYTE[#previous_wallp]=='\\')
{
for (j=0; j<select_list.count; j++) {
if (streq(list.get(j), #previous_wallp+4)) {
active_wallpaper = j;
break;
}
}
}
select_list.cur_y = active_wallpaper;
}
if (!select_list.count) notify(T_NO_FILES);
if (select_list.cur_y>SL_VISIBLE) {
select_list.first = -SL_VISIBLE/2 + select_list.cur_y;
}
select_list.CheckDoesValuesOkey();
if (LIST_W) draw_window();
}
void SelectList_DrawLine(dword i)
{
int draw_y = i*SELECT_LIST_ITEMH+PANEL_H;
int i_abs = select_list.first + i;
dword text_color = 0xFFFfff;
dword bg_color = 0x000000;
char filename_buf[PATHLEN];
char* filename = #filename_buf;
strcpy(filename, list.get(i_abs));
if (EAX = strrchr(filename,'/')) filename += EAX;
if (ESBYTE[filename]=='T') && (ESBYTE[filename+1]=='_') filename+=2;
EAX = math.min(strrchr(filename,'.')-1, LIST_W - 24 / 8);
if(EAX) ESBYTE[filename+EAX] = '\0';
//save current item for tab change
switch(tabs.active_tab) {
CASE TAB_SKINS:
active_skin = select_list.cur_y;
if (!i_abs) filename = T_DEFAULT;
BREAK;
CASE TAB_WALLPAPERS:
active_wallpaper = select_list.cur_y;
if (!i_abs) filename = T_DEFAULT;
BREAK;
CASE TAB_SCREENSAVERS:
active_screensaver = select_list.cur_y;
if (!i_abs) filename = T_NO_SS;
}
if (select_list.cur_y == i_abs) {
text_color = sc.button;
bg_color = sc.button_text;
}
DrawBar(select_list.x, draw_y, LIST_W, SELECT_LIST_ITEMH, text_color);
WriteText(select_list.x+12,draw_y+select_list.text_y,select_list.font_type,bg_color, filename);
}
void GetIniSettings()
{
ini.section = "style";
ini.GetString("default_skin", #default_skin, PATHLEN, 0);
ini.GetString("default_wallp", #default_wallp, PATHLEN, 0);
ini.GetString("skin", #previous_skin, PATHLEN, 0);
ini.GetString("bg_param", #previous_wallp, PATHLEN, 0);
ini.section = "screensaver";
ss_timeout.position = ini.GetInt("timeout", 10) - 1;
ini.GetString("available", #ss_available, sizeof(ss_available), 0);
ini.GetString("program", #previous_ss, PATHLEN, 0);
}
//===================================================//
// //
// EVENTS //
// //
//===================================================//
void EventTabSkinsClick()
{
miniprintf(#folder_path, "%s/res/skins", get_real_kolibrios_path());
Open_Dir();
}
void EventTabWallpappersClick()
{
if (opendir_path) {
strcpy(#folder_path, #opendir_path);
} else {
miniprintf(#folder_path, "%s/res/wallpapers", get_real_kolibrios_path());
}
Open_Dir();
}
void EventTabScreensaverClick()
{
dword j;
char ssmas[sizeof(ss_available)];
list.drop();
select_list.ClearList();
select_list.count++;
list.add("");
strcpy(#ssmas, #ss_available);
do {
j = strrchr(#ssmas, '|');
if (ssmas[j]=='/') {
strcpy(#param, #ssmas + j);
} else {
miniprintf(#param, "/sys/%s", #ssmas + j);
}
list.add(#param);
ESBYTE[#ssmas + j - 1] = '\0';
select_list.count++;
} while (j);
if (active_screensaver == -1) && (ESBYTE[#previous_ss]) {
for (j=0; j<select_list.count; j++) {
if (strstr(list.get(j), #previous_ss)) active_screensaver = j;
}
}
select_list.cur_y = active_screensaver;
if (LIST_W) draw_window();
}
void EventDeleteFile()
{
if (select_list.cur_y) DeleteFile(list.get(select_list.cur_y)); //no not delete default
Open_Dir();
EventApply();
}
void EventSelectWallpFolder()
{
o_dialog.type = 2; //select folder
OpenDialog_start stdcall (#o_dialog);
if (o_dialog.status) EventTabWallpappersClick();
}
void EventSetWallpMode(dword _stretch, _titled, _auto)
{
optionbox_stretch.checked = _stretch;
optionbox_tiled.checked = _titled;
optionbox_auto.checked = _auto;
optionbox_tiled.redraw();
optionbox_stretch.redraw();
optionbox_auto.redraw();
EventApply();
}
void EventApply()
{
char kivparam[4096+10];
dword file_name = list.get(select_list.cur_y);
if (tabs.active_tab==TAB_SKINS)
{
strcpy(#cur_skin_path, list.get(select_list.cur_y));
SetSystemSkin(#cur_skin_path);
MoveSize(OLD, OLD, OLD, WIN_H+4+GetSkinHeight());
}
if (tabs.active_tab==TAB_WALLPAPERS)
{
SelectList_Draw();
miniprintf(#kivparam, "\\S__%s", list.get(select_list.cur_y));
if (optionbox_tiled.checked) || (!select_list.cur_y) kivparam[1]='T';
if (optionbox_auto.checked) {
file_name += strrchr(file_name, '/');
if (ESBYTE[file_name] == 'T') && (ESBYTE[file_name+1] == '_') {
kivparam[1]='T';
}
}
RunProgram("/sys/media/kiv", #kivparam);
}
if (tabs.active_tab==TAB_SCREENSAVERS)
{
SelectList_Draw();
}
}
void EventOpenFile()
{
switch (tabs.active_tab) {
case TAB_SKINS:
RunProgram("/sys/skincfg", list.get(select_list.cur_y));
break;
case TAB_WALLPAPERS:
RunProgram("/sys/media/kiv", list.get(select_list.cur_y));
break;
case TAB_SCREENSAVERS:
if(select_list.cur_y) {
KillProcessByName("@ss", MULTIPLE);
RunProgram(list.get(select_list.cur_y), "@ss");
}
}
}
void EventExit()
{
if (get_real_kolibrios_path()) && (ESBYTE[#cur_skin_path]) {
ini.section = "style";
ini.SetString("skin", #cur_skin_path, strlen(#cur_skin_path));
}
ExitProcess();
}
void EventSetSs()
{
dword cur_ss = list.get(select_list.cur_y);
ini.section = "screensaver";
ini.SetString("program", cur_ss, strlen(cur_ss));
ini.SetInt("timeout", ss_timeout.position+1);
RestartProcessByName("/sys/@ss", MULTIPLE);
}
stop:
char folder_path[PATHLEN];
char cur_skin_path[PATHLEN];
char default_skin[PATHLEN];
char default_wallp[PATHLEN];
char previous_skin[PATHLEN];
char previous_wallp[PATHLEN];
char previous_ss[PATHLEN];
+5
View File
@@ -0,0 +1,5 @@
@c-- /D=LANG_ENG appearance.c
@del *.
@rename *.com *.
@del warning.txt
if not exist appearance ( @pause )
+5
View File
@@ -0,0 +1,5 @@
@c-- /D=LANG_RUS appearance.c
@del *.
@rename *.com *.
@del warning.txt
if not exist appearance ( @pause )
+106
View File
@@ -0,0 +1,106 @@
#ifdef LANG_RUS
char t_skins[] = " Стиль окон";
char t_wallpapers[] = " Обои";
char t_screensaver[] = " Скринсейвер";
?define WINDOW_HEADER "Настройки оформления"
?define T_SELECT_FOLDER "Выбрать папку"
?define T_PICTURE_MODE " Положение картинки "
?define T_CHECKBOX_STRETCH "Растянуть"
?define T_CHECKBOX_TILED "Замостить"
?define T_CHECKBOX_AUTO "Автоматически"
?define T_UPDATE_DOCK "Обновлять Dock-панель"
?define T_NO_FILES "'Поддерживаемые файлы не найдены' -E"
?define T_UI_PREVIEW " Пример компонентов "
?define T_SS_TIMEOUT "Интервал в минутах: %i "
?define T_SS_PREVIEW "Просмотр"
?define T_SS_SET "Установить"
?define T_NO_SS "[Выключен]"
?define T_DEFAULT "[По умолчанию]"
#else
char t_skins[] = " Skins";
char t_wallpapers[] = " Wallpapers";
char t_screensaver[] = " Screensaver";
?define WINDOW_HEADER "Appearance"
?define T_SELECT_FOLDER "Select folder"
?define T_PICTURE_MODE " Picture Mode "
?define T_CHECKBOX_STRETCH "Stretch"
?define T_CHECKBOX_TILED "Tiled"
?define T_CHECKBOX_AUTO "Auto"
?define T_UPDATE_DOCK "Update Dock"
?define T_NO_FILES "'No supported files were found' -E"
?define T_UI_PREVIEW " Components Preview "
?define T_SS_TIMEOUT "Wait in minutes: %i "
?define T_SS_PREVIEW "View"
?define T_SS_SET "Set"
?define T_NO_SS "[Disable]"
?define T_DEFAULT "[Default]"
#endif
#define WIN_W 560
#define WIN_H 445
#define LIST_W 260
#define PANEL_H 50
#define LP 6 //LIST_PADDING
#define SL_VISIBLE WIN_H - PANEL_H - LP / SELECT_LIST_ITEMH
#define RIGHTx LP + LIST_W + TAB_P + 30
#define RIGHTy PANEL_H
#define RIGHTw WIN_W - RIGHTx - LP - TAB_P
#define RIGHTh 215
enum {
TAB_SKINS,
TAB_WALLPAPERS,
TAB_SCREENSAVERS
};
enum {
BASE_TAB_BUTTON_ID=3,
BTN_SELECT_WALLP_FOLDER=10,
BTN_TEST_SCREENSAVER,
BTN_SET_SCREENSAVER
};
_ini ini = { "/sys/settings/system.ini" };
char default_dir[] = "/sys";
od_filter filter2 = { 8, "TXT\0\0" };
_tabs tabs = { -sizeof(t_skins)-sizeof(t_wallpapers)-sizeof(t_screensaver)
-3*8+WIN_W - TAB_P / 2, LP, NULL, BASE_TAB_BUTTON_ID };
scroll_bar ss_timeout = { RIGHTw-19,RIGHTx,15,RIGHTy+25,0,3,89,10,0,0xFFFfff,
0xBBBbbb,0xeeeeee};
void sort_by_name(int a, b) // for the first call: a = 0, b = sizeof(mas) - 1
{
int j;
int isn = a;
if (a >= b) return;
for (j = a; j <= b; j++) {
if (strcmpi(io.dir.position(ESDWORD[j*4+fmas]), io.dir.position(ESDWORD[b*4+fmas]))<=0) {
ESDWORD[isn*4+fmas] >< ESDWORD[j*4+fmas];
isn++;
}
}
sort_by_name(a, isn-2);
sort_by_name(isn, b);
}
dword get_real_kolibrios_path()
{
char real_kolibrios_path[256];
if (!dir_exists("/kolibrios")) return 0;
SetCurDir("/kolibrios");
GetCurDir(#real_kolibrios_path, sizeof(real_kolibrios_path));
return #real_kolibrios_path;
}
void SelectList_LineChanged()
{
EventApply();
}
@@ -0,0 +1,33 @@
checkbox checkbox1 = { "Checkbox", true };
more_less_box spinbox1 = { 23, 0, 999, "SpinBox" };
edit_box edit_cmm = {180,NULL,NULL,0xffffff,0x94AECE,0xFFFfff,0xffffff,
0x10000000,sizeof(param)-2,#param,0, 0b};
char st_str[16];
edit_box edit_st = {180,NULL,NULL,0xffffff,0x94AECE,0xFFFfff,0xffffff,
0x10000000,sizeof(st_str)-2,#st_str,0, 0b};
void DrawUiElementsPreview(dword x,y,h)
{
incn y2;
spinbox1.draw(x, y2.set(y+30));
WriteText(x, y2.inc(30), 0x90, sc.work_text, "C-- Edit");
DrawEditBoxPos(x, y2.inc(20), #edit_cmm);
WriteText(x, y2.inc(35), 0x90, sc.work_text, "Standard Edit");
DrawStEditBoxPos(x, y2.inc(20), #edit_st);
DrawStandartCaptButton(x, y+h-40, GetFreeButtonId(), "Button1");
DrawStandartCaptButton(x+100, y+h-40, GetFreeButtonId(), "Button2");
}
:void DrawStEditBoxPos(dword x,y, edit_box_pointer)
{
dword c_inactive = MixColors(sc.line, sc.work, 128);
dword c_active = MixColors(sc.line, 0, 128);
ESI = edit_box_pointer;
ESI.edit_box.left = x;
ESI.edit_box.top = y;
ESI.edit_box.border_color = c_inactive;
ESI.edit_box.focus_border_color = c_active;
edit_box_draw stdcall (edit_box_pointer);
}
+6
View File
@@ -0,0 +1,6 @@
if tup.getconfig("NO_CMM") ~= "" then return end
if tup.getconfig("LANG") == "ru_RU"
then C_LANG = "LANG_RUS"
else C_LANG = "LANG_ENG" -- this includes default case without config
end
tup.rule("barscfg.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "barscfg.com")
Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.
Binary file not shown.
+317
View File
@@ -0,0 +1,317 @@
#define MEMSIZE 1024*40
#include "..\lib\kolibri.h"
#include "..\lib\strings.h"
#include "..\lib\mem.h"
#include "..\lib\fs.h"
#include "..\lib\dll.h"
#include "..\lib\gui.h"
#include "..\lib\obj\libini.h"
#include "..\lib\obj\box_lib.h"
#include "..\lib\patterns\restart_process.h"
#ifdef LANG_RUS
?define WINDOW_TITLE "Настройки панели задач и Дока"
?define TASK_FRAME_T " Панель задач "
?define DOCK_FRAME_T " Док "
?define MIN_LEFT_BUTTON "Кнопка скрытия слева"
?define MIN_RIGHT_BUTTON "Кнопка скрытия справа"
?define SOFTEN_UP "Сглаживание сверху"
?define SOFTEN_DOWN "Сглаживание снизу"
?define CLOCK "Часы"
?define CPU_USAGE "Загрузка ЦП"
?define CHANGE_LANG "Язык ввода"
?define MENU_BUTTON "Кнопка меню"
?define PANEL_HEIGHT "Высота панели"
?define SOFTEN_HEIGHT "Высота сглаживания"
?define BUTTON_OFFSET "Поле вокруг кнопок"
?define FSIZE "Режим панели"
?define ASHOW "Не скрывать"
?define CHANGE_POS "Нажмите на изображение для смены позиции"
#else
?define WINDOW_TITLE "Taskbar and Docky configuration"
?define TASK_FRAME_T " Taskbar "
?define DOCK_FRAME_T " Docky "
?define MIN_LEFT_BUTTON "Min Left Button"
?define MIN_RIGHT_BUTTON "Min Right Button"
?define SOFTEN_UP "Soften Up"
?define SOFTEN_DOWN "Soften Down"
?define CLOCK "Clock"
?define CPU_USAGE "Cpu Usage"
?define CHANGE_LANG "Change Language"
?define MENU_BUTTON "Menu Button"
?define PANEL_HEIGHT "Panel Height"
?define SOFTEN_HEIGHT "Soften Height"
?define BUTTON_OFFSET "Button Offset"
?define FSIZE "Full width"
?define ASHOW "Always show"
?define CHANGE_POS "Click on image to change position"
#endif
char taskbar_ini_path[] = "/sys/settings/taskbar.ini";
_ini taskbar_flags_ini = { #taskbar_ini_path, "Flags" };
_ini taskbar_vars_ini = { #taskbar_ini_path, "Variables" };
_ini docky_ini = { "/sys/settings/docky.ini", "@" };
#define PIMG_W 37
#define PIMG_H 27 //27*5
unsigned char panels_img_data[] = FROM "bars_8b.raw";
dword panels_img_pal[] = {
0x00405D74,0x0084FC84,0x00FAFAFA,0x0000B400,
0x00E4E4E4,0x008C9B9C,0x000212FD,0x00D8DEDF,
0x00585C5D,0x0085B7E0,0x009EC6E7,0x0094C0E5,
0x00CB8800,0x00CE3D9E,0x00D20404,0x00485966
};
proc_info Form;
enum { BTN_TB_ATTACHEMENT=100, BTN_DOCKY_ATTACHEMENT=200 };
enum { TASKBAR, DOCKY };
more_less_box tbPanelHeight = { NULL, 6, 99, PANEL_HEIGHT };
more_less_box tbSoftenHeight = { NULL, 0, 99, SOFTEN_HEIGHT };
more_less_box tbButtonOffset = { NULL, 0, 99, BUTTON_OFFSET };
checkbox taskbar_on = 0;
checkbox docky_on = 0;
int tbAttachment;
checkbox tbSoftenUp = { SOFTEN_UP };
checkbox tbClock = { CLOCK };
checkbox tbSoftenDown = { SOFTEN_DOWN };
checkbox tbCpuUsage = { CPU_USAGE };
checkbox tbMinLeftButton = { MIN_LEFT_BUTTON };
checkbox tbChangeLang = { CHANGE_LANG };
checkbox tbMinRightButton = { MIN_RIGHT_BUTTON };
checkbox tbMenuButton = { MENU_BUTTON };
checkbox dkFsize = { FSIZE };
checkbox dkAshow = { ASHOW };
int dkLocation=0;
checkbox tbRunApplButton;
checkbox tbClnDeskButton;
void main()
{
dword id;
load_dll(libini, #lib_init,1);
load_dll(boxlib, #box_lib_init,0);
LoadCfg();
loop() switch(@WaitEvent())
{
case evButton:
id = @GetButtonID();
if (1==id) @ExitProcess();
if (taskbar_on.checked) EventTaskbarProcessButton(id);
if (docky_on.checked) EventDockyProcessButton(id);
if (taskbar_on.click(id)) {
IF (taskbar_on.checked == true) RunProgram("/sys/@taskbar", 0);
ELSE KillProcessByName("@TASKBAR", SINGLE);
DrawWindowContent();
}
if (docky_on.click(id)) {
IF (docky_on.checked == true) {
dkLocation = 2;
SaveSettingsAndRestartProcess(DOCKY);
} ELSE {
KillProcessByName("@DOCKY", SINGLE);
}
DrawWindowContent();
}
break;
case evKey:
if (@GetKeyScancode() == SCAN_CODE_ESC) ExitProcess();
break;
case evReDraw:
sc.get();
DefineAndDrawWindow(130, 150, 465, 398 + skin_h, 0x34, sc.work, WINDOW_TITLE, 0);
GetProcessInfo(#Form, SelfInfo);
if (Form.status_window&ROLLED_UP) break;
DrawWindowContent();
}
}
void DrawPanelsImage(dword y, n)
{
PutPaletteImage(n * PIMG_W * PIMG_H + #panels_img_data, PIMG_W, PIMG_H, 22, y, 8, #panels_img_pal);
}
void SetDisabledMode()
{
EAX = taskbar_on.checked ^ 1;
tbSoftenUp.disabled =
tbSoftenDown.disabled =
tbMinLeftButton.disabled =
tbMinRightButton.disabled =
tbRunApplButton.disabled =
tbClnDeskButton.disabled =
tbClock.disabled =
tbCpuUsage.disabled =
tbChangeLang.disabled =
tbMenuButton.disabled =
tbPanelHeight.disabled =
tbSoftenHeight.disabled =
tbButtonOffset.disabled =
tbButtonOffset.disabled = EAX;
//
dkFsize.disabled =
dkAshow.disabled = docky_on.checked ^ 1;
}
void DrawWindowContent()
{
#define PD 10
dword frame_y;
word win_center_x = Form.cwidth / 2 + 20;
incn y;
int i;
SetDisabledMode();
frame_y = 15;
y.n = frame_y;
DefineButton(22, y.inc(18), PIMG_W-1, PIMG_H-1, 100 + BT_HIDE, 0);
DrawPanelsImage(y.n, tbAttachment);
WriteTextWithBg(68, y.inc(7), 0xD0, sc.work_text, CHANGE_POS, sc.work);
tbSoftenUp.draw(22, y.inc(35));
tbClock.draw(win_center_x, y.n);
tbSoftenDown.draw(22, y.inc(24));
tbCpuUsage.draw(win_center_x, y.n);
tbMinLeftButton.draw(22, y.inc(24));
tbChangeLang.draw(win_center_x, y.n);
tbMinRightButton.draw(22, y.inc(24));
tbMenuButton.draw(win_center_x, y.n);
tbPanelHeight.draw(22, y.inc(28));
tbSoftenHeight.draw(22, y.inc(32));
tbButtonOffset.draw(22, y.inc(32));
DrawFrame(PD, frame_y, Form.cwidth-PD-PD, y.inc(32)-frame_y, TASK_FRAME_T);
taskbar_on.draw(22, frame_y-7);
//DOCKY
frame_y = calc(y.inc(20));
DefineButton(22, y.inc(18), PIMG_W-1, PIMG_H-1, 200 + BT_HIDE, 0);
if (!dkLocation) i=2; else i=dkLocation;
DrawPanelsImage(y.n, i+1);
WriteTextWithBg(68, y.inc(7), 0xD0, sc.work_text, CHANGE_POS, sc.work);
dkFsize.draw(22, y.inc(35));
dkAshow.draw(win_center_x, y.n);
DrawFrame(PD, frame_y, Form.cwidth-PD-PD, Form.cheight-frame_y-PD, DOCK_FRAME_T);
docky_on.draw(22, frame_y-7);
}
void LoadCfg()
{
tbAttachment = taskbar_flags_ini.GetInt("Attachment", 1);
tbSoftenUp.checked = taskbar_flags_ini.GetInt("SoftenUp", 1);
tbSoftenDown.checked = taskbar_flags_ini.GetInt("SoftenDown", 1);
tbMinLeftButton.checked = taskbar_flags_ini.GetInt("MinLeftButton", 1);
tbMinRightButton.checked = taskbar_flags_ini.GetInt("MinRightButton", 1);
tbClock.checked = taskbar_flags_ini.GetInt("Clock", 1);
tbCpuUsage.checked = taskbar_flags_ini.GetInt("CpuUsage", 1);
tbChangeLang.checked = taskbar_flags_ini.GetInt("ChangeLang", 1);
tbMenuButton.checked = taskbar_flags_ini.GetInt("MenuButton", 1);
tbPanelHeight.value = taskbar_vars_ini.GetInt("PanelHeight", 28);
tbSoftenHeight.value = taskbar_vars_ini.GetInt("SoftenHeight", 4);
tbButtonOffset.value = taskbar_vars_ini.GetInt("ButtonTopOffset", 3);
tbButtonOffset.value = taskbar_vars_ini.GetInt("ButtonBotOffset", 3);
dkLocation = docky_ini.GetInt("location", 0);
dkFsize.checked = docky_ini.GetInt("fsize", 0);
dkAshow.checked = docky_ini.GetInt("ashow", 0);
taskbar_on.checked = CheckProcessExists("@TASKBAR");
docky_on.checked = CheckProcessExists("@DOCKY");
}
void SaveSettingsAndRestartProcess(byte panel_type)
{
if (panel_type==TASKBAR) {
taskbar_flags_ini.SetInt("Attachment", tbAttachment);
taskbar_flags_ini.SetInt("SoftenUp", tbSoftenUp.checked);
taskbar_flags_ini.SetInt("SoftenDown", tbSoftenDown.checked);
taskbar_flags_ini.SetInt("MinLeftButton", tbMinLeftButton.checked);
taskbar_flags_ini.SetInt("MinRightButton", tbMinRightButton.checked);
taskbar_flags_ini.SetInt("RunApplButton", tbRunApplButton.checked);
taskbar_flags_ini.SetInt("ClnDeskButton", tbClnDeskButton.checked);
taskbar_flags_ini.SetInt("Clock", tbClock.checked);
taskbar_flags_ini.SetInt("CpuUsage", tbCpuUsage.checked);
taskbar_flags_ini.SetInt("ChangeLang", tbChangeLang.checked);
taskbar_flags_ini.SetInt("MenuButton", tbMenuButton.checked);
taskbar_vars_ini.SetInt("PanelHeight", tbPanelHeight.value);
taskbar_vars_ini.SetInt("SoftenHeight", tbSoftenHeight.value);
taskbar_vars_ini.SetInt("ButtonTopOffset", tbButtonOffset.value);
taskbar_vars_ini.SetInt("ButtonBottOffset", tbButtonOffset.value);
}
if (panel_type==DOCKY) {
if (!docky_on.checked) {
docky_ini.SetInt("location", 0);
} else {
docky_ini.SetInt("location", dkLocation);
}
docky_ini.SetInt("fsize", dkFsize.checked);
docky_ini.SetInt("ashow", dkAshow.checked);
}
RestartProcess(panel_type);
}
void RestartProcess(byte panel_type)
{
dword proc_name1;
if (panel_type == TASKBAR)
{
RestartProcessByName("/sys/@taskbar", SINGLE);
pause(50);
}
else
{
RestartProcessByName("/sys/@docky", SINGLE);
pause(120);
}
GetProcessInfo(#Form, SelfInfo);
ActivateWindow(GetProcessSlot(Form.ID));
}
void EventTaskbarProcessButton(dword id)
{
if (BTN_TB_ATTACHEMENT == id) {
tbAttachment ^= 1;
DrawWindowContent();
SaveSettingsAndRestartProcess(TASKBAR);
}
if (tbSoftenUp.click(id)) || (tbSoftenDown.click(id))
|| (tbMinLeftButton.click(id)) || (tbMinRightButton.click(id))
|| (tbRunApplButton.click(id)) || (tbClnDeskButton.click(id)) {
SaveSettingsAndRestartProcess(TASKBAR);
}
if (tbClock.click(id)) || (tbCpuUsage.click(id))
|| (tbChangeLang.click(id)) || (tbMenuButton.click(id))
|| (tbPanelHeight.click(id)) || (tbSoftenHeight.click(id))
|| (tbButtonOffset.click(id)) {
SaveSettingsAndRestartProcess(TASKBAR);
}
}
void EventDockyProcessButton(dword id)
{
if (BTN_DOCKY_ATTACHEMENT == id) {
dkLocation++;
if (dkLocation>4) dkLocation=1;
DrawWindowContent();
SaveSettingsAndRestartProcess(DOCKY);
}
if (dkFsize.click(id)) || (dkAshow.click(id)) {
SaveSettingsAndRestartProcess(DOCKY);
}
}
stop:
+6
View File
@@ -0,0 +1,6 @@
@c-- /D=LANG_ENG barscfg.c
@pause
@del barscfg
@rename *.com *.
@del warning.txt
+6
View File
@@ -0,0 +1,6 @@
@c-- /D=LANG_RUS barscfg.c
@pause
@del barscfg
@rename *.com *.
@del warning.txt
+285
View File
@@ -0,0 +1,285 @@
#include "TWB\colors.h"
#include "TWB\anchors.h"
#include "TWB\parse_tag.h"
#include "TWB\special.h"
#include "TWB\tag_list.h"
#define DEFAULT_BG_COL 0xffFBE5E4; //- peach; 0xffEBE8E9 - more grey
dword link_color_default;
dword link_color_active;
#include "TWB\links.h"
#define BODY_MARGIN 6
#define BASIC_CHAR_W 8
#define BASIC_LINE_H 18
struct STYLE {
bool
b, u, s, h,
font,
pre,
blq,
button,
image,
nav, header;
LIST tag_list;
dword title;
dword cur_line_h;
void reset();
};
void STYLE::reset()
{
b = u = s = h = font = pre = blq =
title = button = image = nav = header = false;
cur_line_h = NULL;
tag_list.reset();
}
struct TWebBrowser {
llist list;
STYLE style;
dword draw_y, draw_x, draw_w, left_gap;
dword o_bufpointer;
int cur_encoding, custom_encoding;
bool link, t_html, t_body;
dword bufpointer;
dword bufsize;
dword is_html;
collection img_url;
char header[150];
char linebuf[500];
char redirect[URL_SIZE];
bool secondrun;
void SetStyle();
void RenderTextbuf();
void RenderLine();
bool RenderImage();
void SetPageDefaults();
void ParseHtml();
void Reparse();
void NewLine();
void ChangeEncoding();
void AddCharToTheLine();
void DrawPage();
void tag_a();
void tag_p();
void tag_img();
void tag_kosicon();
void tag_div();
void tag_h1234_caption();
void tag_ol_ul_dt();
void tag_li();
void tag_q();
void tag_hr();
void tag_code();
void tag_meta_xml();
void tag_body();
void tag_iframe();
void tag_title();
void tag_font();
void tag_table_reset();
void tag_table();
void tag_td();
void tag_tr();
void reset_font_style();
};
#include "TWB\render.h"
#include "TWB\set_style.h"
//============================================================================================
void TWebBrowser::SetPageDefaults()
{
t_html = t_body = link = false;
style.reset();
reset_font_style();
link_color_default = 0x0000FF;
link_color_active = 0xFF0000;
links.clear();
anchors.clear();
img_url.drop();
text_colors.drop();
text_colors.add(0);
if (secondrun) {
canvas.Init(list.x, list.y, list.w, math.max(list.visible, list.count)+200);
canvas.Fill(0, bg_colors.get(0));
}
bg_colors.drop();
bg_colors.add(DEFAULT_BG_COL);
header = NULL;
draw_y = BODY_MARGIN;
draw_x = left_gap = BODY_MARGIN;
draw_w = list.w - BODY_MARGIN - BODY_MARGIN;
linebuf = 0;
redirect = '\0';
tag_table_reset();
is_html = true;
if (!strstri(bufpointer, "<body")) {
t_body = true;
if (!strstri(bufpointer, "<html")) && (!strstri(bufpointer, "<head")) && (!strstri(bufpointer, "<title"))
&& (!strstr(bufpointer, "<?xml")) && (!strstr(bufpointer, "<xml")) {
style.pre = true; //show linebreaks for a plaint text
is_html = false;
}
}
}
//============================================================================================
void TWebBrowser::Reparse()
{
ParseHtml(bufpointer, bufsize);
}
//============================================================================================
void TWebBrowser::ParseHtml(dword _bufpointer, _bufsize){
int tab_len;
dword bufpos;
bufsize = _bufsize;
if (bufpointer == _bufpointer) {
custom_encoding = cur_encoding;
} else {
bufpointer = malloc(bufsize);
memmov(bufpointer, _bufpointer, bufsize);
//hold original buffer
o_bufpointer = malloc(bufsize);
memmov(o_bufpointer, bufpointer, bufsize);
cur_encoding = CH_CP866;
if (custom_encoding != -1) {
cur_encoding = custom_encoding;
bufpointer = ChangeCharset(cur_encoding, CH_CP866, bufpointer);
bufsize = strlen(bufpointer);
}
}
table.cols.drop();
secondrun = false;
_PARSE_START_:
SetPageDefaults();
for (bufpos=bufpointer; bufpos < bufpointer+bufsize; bufpos++;)
{
if (style.pre) {
if (ESBYTE[bufpos] == 0x0a) {
RenderTextbuf();
NewLine();
continue;
}
if (ESBYTE[bufpos] == 0x09) {
tab_len = draw_x - left_gap / list.font_w + strlen(#linebuf) % 4;
if (!tab_len) tab_len = 4; else tab_len = 4 - tab_len;
while (tab_len) {chrcat(#linebuf,' '); tab_len--;}
continue;
}
}
if (ESBYTE[bufpos] == '&') {
bufpos = GetUnicodeSymbol(#linebuf, sizeof(TWebBrowser.linebuf)-1, bufpos+1, bufpointer+bufsize);
continue;
}
if (ESBYTE[bufpos] == '<') && (is_html) {
if (strchr("!/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", ESBYTE[bufpos+1])) {
bufpos++;
if (tag.parse(#bufpos, bufpointer + bufsize)) {
/*
if (secondrun)
{
if (streq(#tag.name, "tr")) debugln(" ");
if (!tag.opened) {
debugch('/');
} else {
debugch(' ');
}
debugln(sprintf(#param, "%s x%i y%i %s",
#tag.name, draw_x, draw_y, #linebuf));
}
//*/
RenderTextbuf();
if (debug_mode) { debugch('<'); if(!tag.opened)debugch('/'); debug(#tag.name); debugln(">"); }
$push cur_encoding
SetStyle();
$pop eax
// The thing is that UTF if longer than other encodings.
// So if encoding was changed from UTF to DOS than $bufpos position got wrong,
// and we have to start parse from the very beginning
if (EAX != cur_encoding) && (cur_encoding == CH_UTF8) {
ParseHtml(bufpointer, strlen(bufpointer));
return;
}
}
continue;
}
}
AddCharToTheLine(ESBYTE[bufpos]);
}
RenderTextbuf();
list.count = draw_y + style.cur_line_h;
list.CheckDoesValuesOkey();
anchors.current = NULL;
if (!secondrun) {
secondrun = true;
goto _PARSE_START_;
}
if (!header) {
strncpy(#header, #version, sizeof(TWebBrowser.header)-1);
DrawTitle(#header);
}
}
//============================================================================================
void TWebBrowser::AddCharToTheLine(unsigned char _char)
{
dword line_len = strlen(#linebuf);
if (_char<=15) _char=' ';
if (!style.pre) && (_char == ' ')
{
if (linebuf[line_len-1]==' ') return; //no double spaces
if (draw_x==left_gap) && (!linebuf) return; //no paces at the beginning of the line
if (link) && (line_len==0) return;
}
if (line_len < sizeof(TWebBrowser.linebuf)) {
chrcat(#linebuf+line_len, _char);
} else {
RenderTextbuf();
}
}
//============================================================================================
void TWebBrowser::ChangeEncoding(int _new_encoding)
{
if (cur_encoding == _new_encoding) return;
cur_encoding = _new_encoding;
bufpointer = ChangeCharset(cur_encoding, CH_CP866, bufpointer);
if (header) {
ChangeCharset(cur_encoding, CH_CP866, #header);
DrawTitle(#header);
}
}
//============================================================================================
scroll_bar scroll_wv = { 15,NULL,NULL,NULL,
0,2,NULL,0,0,0xeeeeee,0xBBBbbb,0xeeeeee};
void TWebBrowser::DrawPage()
{
if (list.w!=canvas.bufw) Reparse();
canvas.Show(list.first, list.h);
scroll_wv.max_area = list.count;
scroll_wv.cur_area = list.visible;
scroll_wv.position = list.first;
scroll_wv.all_redraw = 0;
scroll_wv.start_x = list.x + list.w;
scroll_wv.start_y = list.y;
scroll_wv.size_y = list.h;
if (list.count <= list.visible) {
DrawBar(scroll_wv.start_x, scroll_wv.start_y, scroll_wv.size_x,
scroll_wv.size_y, bg_colors.get(0) & 0x00FFFFFF);
} else {
scrollbar_v_draw(#scroll_wv);
}
}
+43
View File
@@ -0,0 +1,43 @@
struct _anchors {
char current[256];
collection anchor_name;
collection anchor_position;
void add();
int get_pos_by_name();
void clear();
void take_anchor_from();
} anchors=0;
void _anchors::add(dword _name, _pos)
{
anchor_name.add(_name);
anchor_position.add(itoa(_pos));
}
int _anchors::get_pos_by_name(dword _get_name)
{
dword pos_name = anchor_name.get_pos_by_name(_get_name);
if (ESBYTE[_get_name]==NULL) return 0;
if (pos_name==-1) {
return -1;
} else {
return atoi(anchor_position.get(pos_name));
}
}
void _anchors::clear()
{
anchor_name.drop();
anchor_position.drop();
}
void _anchors::take_anchor_from(dword _URL)
{
int anchor_pos;
if (!current) && (_URL) && (anchor_pos = strrchr(_URL, '#')) {
strncpy(#current, _URL+anchor_pos-1, sizeof(_anchors.current)-1);
ESBYTE[_URL+anchor_pos-1] = '\0';
}
}
+75
View File
@@ -0,0 +1,75 @@
collection_int text_colors;
collection_int bg_colors;
struct WEB_COLORS {
char *name;
dword rgb;
} web_colors[] = {
"aliceblue", 0xF0F8FF, "antiquewhite", 0xFAEBD7, "aqua", 0x00FFFF, "aquamarine", 0x7FFFD4,
"azure", 0xF0FFFF, "beige", 0xF5F5DC, "bisque", 0xFFE4C4, "black", 0x000000,
"blanchedalmond", 0xFFEBCD, "blue", 0x0000FF, "blueviolet", 0x8A2BE2, "brown", 0xA52A2A,
"burlywood", 0xDEB887, "cadetblue", 0x5F9EA0, "chartreuse", 0x7FFF00, "chocolate", 0xD2691E,
"coral", 0xFF7F50, "cornflowerblue", 0x6495ED, "cornsilk", 0xFFF8DC, "crimson", 0xDC143C,
"cyan", 0x00FFFF, "darkblue", 0x00008B, "darkcyan", 0x008B8B, "darkgoldenrod", 0xB8860B,
"darkgray", 0xA9A9A9, "darkgreen", 0x006400, "darkkhaki", 0xBDB76B, "darkmagenta", 0x8B008B,
"darkolivegreen", 0x556B2F, "darkorange", 0xFF8C00, "darkorchid", 0x9932CC, "darkred", 0x8B0000,
"darksalmon", 0xE9967A, "darkseagreen", 0x8FBC8F, "darkslateblue", 0x483D8B, "darkslategray", 0x2F4F4F,
"darkturquoise", 0x00CED1, "darkviolet", 0x9400D3, "deeppink", 0xFF1493, "deepskyblue", 0x00BFFF,
"dimgray", 0x696969, "dodgerblue", 0x1E90FF, "firebrick", 0xB22222, "floralwhite", 0xFFFAF0,
"forestgreen", 0x228B22, "fuchsia", 0xFF00FF, "gainsboro", 0xDCDCDC, "ghostwhite", 0xF8F8FF,
"gold", 0xFFD700, "goldenrod", 0xDAA520, "gray", 0x808080, "green", 0x008000,
"greenyellow", 0xADFF2F, "honeydew", 0xF0FFF0, "hotpink", 0xFF69B4, "indianred", 0xCD5C5C,
"indigo", 0x4B0082, "ivory", 0xFFFFF0, "khaki", 0xF0E68C, "lavender", 0xE6E6FA,
"lavenderblush", 0xFFF0F5, "lawngreen", 0x7CFC00, "lemonchiffon", 0xFFFACD, "lightblue", 0xADD8E6,
"lightcoral", 0xF08080, "lightcyan", 0xE0FFFF, "lightgreen", 0x90EE90, "lightgrey", 0xD3D3D3,
"lightpink", 0xFFB6C1, "lightsalmon", 0xFFA07A, "lightseagreen", 0x20B2AA, "lightskyblue", 0x87CEFA,
"lightslategray", 0x778899, "lightsteelblue", 0xB0C4DE, "lightyellow", 0xFFFFE0, "lime", 0x00FF00,
"limegreen", 0x32CD32, "linen", 0xFAF0E6, "magenta", 0xFF00FF, "maroon", 0x800000,
"mediumaquamarine", 0x66CDAA, "mediumblue", 0x0000CD, "mediumorchid", 0xBA55D3, "mediumpurple", 0x9370DB,
"mediumseagreen", 0x3CB371, "mediumslateblue", 0x7B68EE, "mediumspringgreen",0x00FA9A, "mediumturquoise", 0x48D1CC,
"mediumvioletred", 0xC71585, "midnightblue", 0x191970, "mintcream", 0xF5FFFA, "mistyrose", 0xFFE4E1,
"moccasin", 0xFFE4B5, "navajowhite", 0xFFDEAD, "navy", 0x000080, "oldlace", 0xFDF5E6,
"olive", 0x808000, "olivedrab", 0x6B8E23, "orange", 0xFFA500, "orangered", 0xFF4500,
"orchid", 0xDA70D6, "palegoldenrod", 0xEEE8AA, "palegreen", 0x98FB98, "paleturquoise", 0xAFEEEE,
"palevioletred", 0xDB7093, "papayawhip", 0xFFEFD5, "peachpuff", 0xFFDAB9, "peru", 0xCD853F,
"pink", 0xFFC0CB, "plum", 0xDDA0DD, "powderblue", 0xB0E0E6, "purple", 0x800080,
"red", 0xFF0000, "rosybrown", 0xBC8F8F, "royalblue", 0x4169E1, "saddlebrown", 0x8B4513,
"salmon", 0xFA8072, "sandybrown", 0xF4A460, "seagreen", 0x2E8B57, "seashell", 0xFFF5EE,
"sienna", 0xA0522D, "silver", 0xC0C0C0, "skyblue", 0x87CEEB, "slateblue", 0x6A5ACD,
"slategray", 0x708090, "snow", 0xFFFAFA, "springgreen", 0x00FF7F, "steelblue", 0x4682B4,
"tan", 0xD2B48C, "teal", 0x008080, "thistle", 0xD8BFD8, "tomato", 0xFF6347,
"turquoise", 0x40E0D0, "violet", 0xEE82EE, "wheat", 0xF5DEB3, "white", 0xFFFFFF,
"whitesmoke", 0xF5F5F5, "yellow", 0xFFFF00, "yellowgreen", 0x9ACD32, 0};
dword GetColor(char* color_str)
{
int ii;
dword textlen=0;
dword color=0;
strlwr(color_str);
if (ESBYTE[color_str] == '#') {
color_str++;
} else {
for (ii=0; web_colors[ii].name!=0; ii++)
{
if (streq(color_str, web_colors[ii].name)) return web_colors[ii].rgb;
}
}
textlen = strlen(color_str);
if (textlen==6) || (textlen==3)
{
FOR (ii=0; ii<textlen; ii++)
{
BL = ESBYTE[color_str+ii];
IF ((BL>='0') && (BL<='9')) BL -= '0';
//IF ((BL>='A') && (BL<='F')) BL -= 'A'-10;
IF ((BL>='a') && (BL<='f')) BL -= 'a'-10;
color = color*0x10 + BL;
if (textlen==3) color = color*0x10 + BL; //#abc ->> #aabbcc
}
return color;
}
return text_colors.get(0);
}
+113
View File
@@ -0,0 +1,113 @@
CustomCursor CursorPointer;
dword CursorFile = FROM "TWB/pointer.cur";
#include "..\lib\collection.h"
struct PAGE_LINKS {
collection unic_links;
collection element_links;
collection_int x;
collection_int y;
collection_int w;
collection_int h;
collection_int id;
collection_int underline_h;
signed int active;
dword active_url;
bool hover();
void add_link();
void add_text();
void clear();
void draw_underline();
} links;
void PAGE_LINKS::add_link(dword lpath)
{
unic_links.add(lpath);
}
void PAGE_LINKS::add_text(dword _x, _y, _w, _h, _underline_h)
{
x.add(_x);
y.add(_y);
w.add(_w);
h.add(_h);
underline_h.add(_underline_h);
element_links.add(unic_links.get_last());
id.add(unic_links.count);
}
void PAGE_LINKS::clear()
{
x.drop();
y.drop();
w.drop();
h.drop();
underline_h.drop();
id.drop();
element_links.drop();
unic_links.drop();
active = -1;
active_url = 0;
CursorPointer.Restore();
}
void PAGE_LINKS::draw_underline(signed _id, dword list_first, list_y, color)
{
int i;
if (_id == -1) return;
for (i=0; i<id.count; i++)
{
if (id.get(i) - id.get(_id) == 0)
&& (y.get(i) + h.get(i) - list_first > list_y) {
DrawBar(x.get(i), y.get(i) + h.get(i) - list_first,
w.get(i), underline_h.get(i), color);
}
}
}
bool PAGE_LINKS::hover(dword list_y, list_first)
{
int i;
int mx = mouse.x;
int my = mouse.y + list_first;
if (!id.count) return false;
//Here we check is any link hovered
for (i=0; i<id.count; i++)
{
if (mx>x.get(i)) && (my>y.get(i))
&& (mx<x.get(i)+w.get(i)) && (my<y.get(i)+h.get(i))
&& (my>list_y+list_first)
{
if (active!=i) {
CursorPointer.Load(#CursorFile);
CursorPointer.Set();
draw_underline(active, list_first, list_y, link_color_default);
draw_underline(i, list_first, list_y, DEFAULT_BG_COL);
active_url = element_links.get(i);
active = i;
DrawStatusBar(active_url);
}
if (mouse.lkm) && (mouse.down) {
DrawRectangle(x.get(active), -list_first + y.get(active),
w.get(active), h.get(active), 0);
}
return true;
}
}
if (active_url) {
CursorPointer.Restore();
draw_underline(active, list_first, list_y, link_color_default);
active_url = 0;
active = -1;
DrawStatusBar(NULL);
}
return false;
}
+202
View File
@@ -0,0 +1,202 @@
/*
struct _DOM {
collection tag;
collection tagparam;
collection_int parent;
} dom;
*/
struct _tag
{
char name[32];
char prior[32];
bool opened;
collection attributes;
collection values;
dword value;
dword number;
bool is();
bool parse();
dword get_next_param();
dword get_value_of();
signed get_number_of();
} tag=0;
bool _tag::is(dword _text)
{
return streq(#name, _text);
}
bool _tag::parse(dword _bufpos, bufend)
{
bool retok = true;
dword bufpos = ESDWORD[_bufpos];
dword params, paramsend;
dword closepos;
dword whitepos;
dword openpos;
if (name) strcpy(#prior, #name); else prior = '\0';
name = '\0';
attributes.drop();
values.drop();
if (!strncmp(bufpos,"!--",3))
{
bufpos+=3;
//STRSTR
while (strncmp(bufpos,"-->",3)!=0) && (bufpos < bufend)
{
bufpos++;
}
bufpos+=2;
retok = false;
goto _RET;
}
if (ESBYTE[bufpos] == '/') {
opened = false;
bufpos++;
} else {
opened = true;
}
closepos = strchr(bufpos, '>');
whitepos = strchrw(bufpos, bufend-bufpos);
if (!whitepos) || (whitepos > closepos) {
//no param
strncpy(#name, bufpos, math.min(closepos - bufpos, sizeof(tag.name)-1));
bufpos = closepos;
} else {
//we have param
while (chrlnum(whitepos, '\"', closepos - whitepos)%2) { //alt="Next>>"
if (!openpos = strchr(closepos+1, '<')) break;
if (openpos < strchr(closepos+1, '>')) break;
if (!closepos = EAX) {closepos = bufend;break;}
}
strncpy(#name, bufpos, math.min(whitepos - bufpos, sizeof(tag.name)-1));
bufpos = closepos;
params = malloc(closepos - whitepos + 1);
strncpy(params, whitepos, closepos - whitepos);
paramsend = params + closepos - whitepos;
while (paramsend = get_next_param(params, paramsend-1));
free(params);
}
if (name) {
strlwr(#name);
// ignore text inside the next tags
if (is("script")) || (is("style")) || (is("binary")) || (is("select")) {
strcpy(#prior, #name);
sprintf(#name, "</%s>", #prior);
if (strstri(bufpos, #name)) bufpos = EAX-1;
retok = false;
} else {
if (name[strlen(#name)-1]=='/') name[strlen(#name)-1]=NULL; //for <br/>
}
} else {
retok = false;
}
_RET:
ESDWORD[_bufpos] = bufpos;
return retok;
}
dword _tag::get_next_param(dword ps, pe)
{
// "ps" - param start
// "pe" - param end
// "q" - quote char
char q = NULL;
dword initial_pe = pe;
dword fixeq;
dword val;
dword attr;
if (ESBYTE[pe] == '/') pe--;
while (pe>ps) && (__isWhite(ESBYTE[pe])) pe--;
if (ESBYTE[pe] == '"') || (ESBYTE[pe] == '\'')
{
//remove quote
q = ESBYTE[pe];
ESBYTE[pe] = '\0';
pe--;
//find VAL start and copy
pe = strrchr(ps, q) + ps;
val = pe;
if (pe>ps) pe--;
ESBYTE[pe] = '\0';
//find ATTR end
while (pe > ps) && (ESBYTE[pe] != '=') pe--;
ESBYTE[pe] = '\0';
}
else
{
//find VAL start and copy
while (pe > ps) && (ESBYTE[pe] != '=') pe--;
val = pe+1;
ESBYTE[pe] = '\0';
//already have ATTR end
}
if (pe > ps) pe--;
//Fix case: "src ="
while (pe>ps) && (__isWhite(ESBYTE[pe])) {
ESBYTE[pe] = '\0';
pe--;
}
//find ATTR start and copy
while (pe>ps) && (!__isWhite(ESBYTE[pe])) pe--;
attr = pe + 1;
ESBYTE[pe] = '\0';
// Fix case: src=./images/logo?sid=e8ece8b38b
// Exchange '=' and '\0' position.
// attr: src=./images/logo?sid => src
// val: e8ece8b38b => ./images/logo?sid=e8ece8b38b
fixeq = strchr(attr,'=');
if (!q) && (fixeq) {
ESBYTE[val-1] >< ESBYTE[fixeq];
val = fixeq+1;
}
strlwr(attr);
strrtrim(val);
//Fix case: " img.png"
while(__isWhite(ESBYTE[val])) && (val<initial_pe) val++;
attributes.add(attr);
values.add(val);
if (pe==ps) return NULL;
return pe;
}
dword _tag::get_value_of(dword _attr_name)
{
int pos = attributes.get_pos_by_name(_attr_name);
if (pos == -1) {
value = 0;
} else {
value = values.get(pos);
}
return value;
}
signed _tag::get_number_of(dword _attr_name)
{
if (get_value_of(_attr_name)) {
number = atoi(value);
} else {
number = 0;
}
return number;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

+184
View File
@@ -0,0 +1,184 @@
CANVAS canvas;
void TWebBrowser::RenderLine(dword _line)
{
unsigned px; //paint x coordinate
unsigned pw; //paint y coordinate
dword pc; //paint color
int zoom;
if (style.title)
{
strncpy(#header, _line, sizeof(TWebBrowser.header)-1);
strncat(#header, " - ", sizeof(TWebBrowser.header)-1);
strncat(#header, #version, sizeof(TWebBrowser.header)-1);
}
else if (t_html) && (!t_body) {
//
}
else if (ESBYTE[_line])
{
pw = strlen(_line) * list.font_w;
zoom = list.font_w / BASIC_CHAR_W;
//there is some shit happens!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (debug_mode) && (pw > draw_w + BODY_MARGIN) {
debugln("anomaly");
debugln(_line);
}
if (debug_mode) {
canvas.DrawBar(draw_x, draw_y, pw, list.item_h, 0xCCCccc);
debugln(_line);
}
style.cur_line_h = math.max(style.cur_line_h, list.item_h);
if (!secondrun) goto _SKIP_DRAW;
if (bg_colors.get_last() - bg_colors.get(0)) {
canvas.DrawBar(draw_x, draw_y, pw, list.item_h, bg_colors.get_last());
}
if (style.image) {
canvas.DrawBar(draw_x, draw_y, pw, list.item_h-1, 0xF9DBCB);
}
if (style.button) {
canvas.DrawBar(draw_x, draw_y, pw, list.item_h - calc(zoom*2), 0xCCCccc);
canvas.DrawBar(draw_x, draw_y + list.item_h - calc(zoom*2), pw, zoom, 0x999999);
}
pc = text_colors.get_last();
if (link) && (pc == text_colors.get(0)) pc = link_color_default;
canvas.WriteText(draw_x, draw_y+1, list.font_type, pc, _line, NULL);
if (style.b) canvas.WriteText(draw_x+1, draw_y+1, list.font_type, pc, _line, NULL);
if (style.s) canvas.DrawBar(draw_x, list.item_h / 2 - zoom + draw_y, pw, zoom, pc);
if (style.u) canvas.DrawBar(draw_x, draw_y + list.font_h, pw, zoom, pc);
if (link) {
if (ESBYTE[_line]==' ') && (ESBYTE[_line+1]==NULL) {} else {
canvas.DrawBar(draw_x, draw_y + list.font_h, pw, zoom, link_color_default);
links.add_text(draw_x, draw_y + list.y, pw, list.font_h, zoom);
}
}
_SKIP_DRAW:
draw_x += pw;
}
ESBYTE[_line] = NULL;
}
void TWebBrowser::RenderTextbuf()
{
dword lbp = #linebuf;
int br; //break position
char nul = '\0';
unsigned int len;
//Do we need a line break?
if (!linebuf[0]) return;
while (len = strlen(lbp)) && (len * list.font_w + draw_x - left_gap >= draw_w) {
//Yes, we do. Lets calculate where...
br = len;
//Is a new line fits in the maximum line width?
if (br * list.font_w + draw_x - left_gap >= draw_w) {
br = draw_w - draw_x + left_gap - BODY_MARGIN / list.font_w;
if (br < 0) br = 0;
while(br) {
if (ESBYTE[lbp + br]==' ') || (ESBYTE[lbp + br]=='-') {
if (br < len) br++;
break;
}
br--;
}
}
//Maybe a new line is too big for the whole new line? Then we have to split it
if (!br) && (len * list.font_w >= draw_w) {
br = draw_w - draw_x + left_gap - BODY_MARGIN / list.font_w;
if (br < 0) {
NewLine();
br = draw_w - draw_x + left_gap - BODY_MARGIN / list.font_w;
}
}
if (br) {
ESBYTE[lbp + br] >< nul;
RenderLine(lbp);
ESBYTE[lbp + br] >< nul;
lbp += br;
while (ESBYTE[lbp]==' ') && (ESBYTE[lbp]) lbp++;
if (ESBYTE[lbp]) NewLine();
} else {
NewLine();
}
}
RenderLine(lbp);
}
void TWebBrowser::NewLine()
{
static bool empty_line = true;
if (draw_x==left_gap) && (draw_y==BODY_MARGIN) return;
if (t_html) && (!t_body) return;
if (draw_x == style.tag_list.level * 5 * list.font_w + left_gap) {
if (!empty_line) {
empty_line=true;
} else {
return;
}
} else {
empty_line = false;
}
draw_y += style.cur_line_h;
style.cur_line_h = list.item_h;
if (style.blq) draw_x = 6 * list.font_w; else draw_x = 0; //left_gap += style.tag_list.level * 5 * list.font_w ???
draw_x += style.tag_list.level * 5 * list.font_w + left_gap;
}
bool TWebBrowser::RenderImage(dword cur_img)
{
int img_x, img_y, img_w, img_h;
dword imgbuf[44];
if (!cur_img) || (!buf_data) return false;
img_h = ESDWORD[cur_img+8];
img_w = ESDWORD[cur_img+4];
if (img_w + draw_x - left_gap >= draw_w) NewLine();
img_y = draw_y;
if (img_h < list.item_h) img_y += list.item_h - img_h / 2 - 1; else img_y -= 2;
style.cur_line_h = math.max(style.cur_line_h, img_h);
img_w = math.min(img_w, canvas.bufw - draw_x);
if (link) links.add_text(draw_x + list.x, img_y + list.y, img_w, img_h, 0);
if (img_y + img_h >= canvas.bufh) canvas.IncreaseBufSize();
if (secondrun)
{
if (ESDWORD[cur_img+20] != IMAGE_BPP32) {
img_convert stdcall(cur_img, 0, IMAGE_BPP32, 0, 0);
$push eax
img_destroy stdcall(cur_img);
$pop eax
cur_img = EAX;
if (!EAX) return false;
}
imgbuf[04] = canvas.bufw;
imgbuf[08] = canvas.bufh;
imgbuf[20] = IMAGE_BPP32;
imgbuf[24] = buf_data+8;
img_blend stdcall(#imgbuf, cur_img, draw_x, img_y, 0, 0, img_w, img_h);
img_destroy stdcall(cur_img);
}
draw_x += img_w;
if (draw_x - left_gap >= draw_w) NewLine();
return true;
}
+513
View File
@@ -0,0 +1,513 @@
void TWebBrowser::SetStyle()
{
if (tag.get_value_of("name")) || (tag.get_value_of("id")) {
anchors.add(tag.value, draw_y);
if (anchors.current) && (streq(tag.value, #anchors.current+1)) {
list.first = draw_y;
anchors.current = NULL;
}
}
if (tag.is("a")) { tag_a(); return; }
if (tag.is("p")) { tag_p(); return; }
if (tag.is("img")) { tag_img(); return; }
if (tag.is("kosicon")) { tag_kosicon(); return; }
if (tag.is("div")) { tag_div(); return; }
if (tag.is("br")) { /*draw_x++;*/NewLine(); return; }
if (tag.is("nav")) { style.nav = tag.opened; return; }
if (tag.is("header")) { NewLine(); return; }
if (tag.is("article")) { NewLine(); return; }
if (tag.is("footer")) { NewLine(); return; }
if (tag.is("figure")) { NewLine(); return; }
if (tag.is("w:p")) { NewLine(); return; }
if (tag.is("b")) { style.b = tag.opened; return; }
if (tag.is("strong")) { style.b = tag.opened; return; }
if (tag.is("big")) { style.b = tag.opened; return; }
if (tag.is("w:b")) { style.b = tag.opened; return; }
if (tag.is("u")) { style.u = tag.opened; return; }
if (tag.is("ins")) { style.u = tag.opened; return; }
if (tag.is("s")) { style.s = tag.opened; return; }
if (tag.is("strike")) { style.s = tag.opened; return; }
if (tag.is("del")) { style.s = tag.opened; return; }
if (tag.is("pre")) { style.pre = tag.opened; return; }
if (tag.is("blockquote")) { style.blq = tag.opened; return; }
if (tag.is("button")) { style.button = tag.opened; return; }
if (tag.is("dl")) { if (tag.opened) NewLine(); return; }
if (tag.is("w:r")) { if (!tag.opened) style.b = false; return; }
if (tag.is("h1")) { tag_h1234_caption(); return; }
if (tag.is("h2")) { tag_h1234_caption(); return; }
if (tag.is("h3")) { tag_h1234_caption(); return; }
if (tag.is("h4")) { tag_h1234_caption(); return; }
if (tag.is("font")) { tag_font(); return; }
if (tag.is("dt")) { tag_ol_ul_dt(); return; }
if (tag.is("dd")) { tag_ol_ul_dt(); return; }
if (tag.is("ul")) { tag_ol_ul_dt(); return; }
if (tag.is("ol")) { tag_ol_ul_dt(); return; }
if (tag.is("li")) { tag_li(); return; }
if (tag.is("q")) { tag_q(); return; }
if (tag.is("hr")) { tag_hr(); return; }
if (tag.is("meta")) { tag_meta_xml(); return; }
if (tag.is("?xml")) { tag_meta_xml(); return; }
if (tag.is("code")) { tag_code(); return; }
if (tag.is("iframe")) { tag_iframe(); return; }
if (tag.is("caption")) { tag_h1234_caption(); return; }
if (tag.is("title")) { tag_title(); return; }
if (tag.is("body")) { tag_body(); return; }
if (tag.is("html")) { t_html = tag.opened; return; }
if (tag.is("table")) { tag_table(); return; }
if (tag.is("tr")) { tag_table(); return; }
if (tag.is("th")) { tag_table(); return; }
if (tag.is("td")) { tag_table(); return; }
}
void TWebBrowser::tag_p()
{
IF (tag.prior[0] == 'h') || (streq(#tag.prior,"td")) return;
IF (!tag.opened) && (streq(#tag.prior,"p")) return;
NewLine();
}
void TWebBrowser::tag_title()
{
style.title = tag.opened;
if (!tag.opened) DrawTitle(#header);
}
void TWebBrowser::tag_font()
{
style.font = tag.opened;
if (tag.opened)
{
if (tag.get_value_of("bg")) {
bg_colors.add(GetColor(tag.value));
} else {
bg_colors.add(bg_colors.get_last());
}
if (tag.get_value_of("color")) {
text_colors.add(GetColor(tag.value));
} else {
text_colors.add(text_colors.get_last());
}
}
else {
if (text_colors.count>1) text_colors.pop();
if (bg_colors.count>1) bg_colors.pop(); //never pop the last color
}
}
void TWebBrowser::tag_div()
{
//if (streq(#tag.prior,"div")) && (tag.opened) return;
if (streq(#tag.prior,"td")) return;
if (streq(#tag.prior,"div")) return;
if (!tag.opened) && (style.font) text_colors.pop();
NewLine();
}
void TWebBrowser::tag_iframe()
{
if (tag.get_value_of("src")) {
NewLine();
strcpy(#linebuf, "IFRAME: ");
RenderTextbuf();
link=true;
links.add_link(tag.value);
strncpy(#linebuf, tag.value, sizeof(TWebBrowser.linebuf)-1);
RenderTextbuf();
link=false;
NewLine();
}
}
void TWebBrowser::tag_a()
{
if (!secondrun) return;
if (tag.opened)
{
if (tag.get_value_of("href")) && (!strstr(tag.value,"javascript:"))
{
link = true;
links.add_link(tag.value);
}
} else {
link = false;
}
}
void TWebBrowser::tag_meta_xml()
{
if (secondrun) return;
if (custom_encoding == -1) if (tag.get_value_of("charset"))
|| (tag.get_value_of("content")) || (tag.get_value_of("encoding"))
{
EDX = strrchr(tag.value, '=') + tag.value; //search in content=
if (ESBYTE[EDX] == '"') EDX++;
strlwr(EDX);
EAX = get_encoding_type_by_name(EDX);
if (EAX!=-1) ChangeEncoding(EAX);
}
if (streq(tag.get_value_of("http-equiv"), "refresh")) && (tag.get_value_of("content")) {
if (tag.value = strstri(tag.value, "url")) strcpy(#redirect, tag.value);
}
}
signed int get_encoding_type_by_name(dword name)
{
EDX = name;
if (streqrp(EDX,"utf-8")) || (streqrp(EDX,"utf8")) return CH_UTF8;
else if (streqrp(EDX,"windows-1251")) || (streqrp(EDX,"windows1251")) return CH_CP1251;
else if (streqrp(EDX,"dos")) || (streqrp(EDX,"cp-866")) return CH_CP866;
else if (streqrp(EDX,"iso-8859-5")) || (streqrp(EDX,"iso8859-5")) return CH_ISO8859_5;
else if (streqrp(EDX,"koi8-r")) || (streqrp(EDX,"koi8-u")) return CH_KOI8;
return -1;
}
void TWebBrowser::tag_code()
{
if (style.pre = tag.opened) {
bg_colors.add(0xe4ffcb);
} else {
if (bg_colors.count>1) bg_colors.pop(); //never pop the last color
}
}
void TWebBrowser::tag_ol_ul_dt()
{
char type = ESBYTE[#tag.name];
switch(type)
{
case 'd':
if (ESBYTE[#tag.name+1]=='d') style.tag_list.upd_level(tag.opened, type);
if (ESBYTE[#tag.name+1]=='t') style.tag_list.upd_level(false, 'd');
if (tag.opened) NewLine();
break;
case 'u':
case 'o':
if (style.nav) && (style.tag_list.level) NewLine();
style.tag_list.upd_level(tag.opened, type);
if (!tag.opened) && (!style.pre) NewLine();
}
}
void TWebBrowser::tag_li()
{
if (style.nav) {
chrncat(#linebuf, ' ', sizeof(TWebBrowser.linebuf));
} else if (tag.opened) {
if (!style.tag_list.level) style.tag_list.upd_level(1, 'u');
if (!style.pre) NewLine();
if (style.tag_list.order_type() == 'u') {
strcpy(#linebuf, "\31 ");
draw_x = style.tag_list.level * 5 - 2 * list.font_w + left_gap;
}
if (style.tag_list.order_type() == 'o') {
sprintf(#linebuf, "%i. ", style.tag_list.inc_counter());
draw_x = style.tag_list.level * 5 - 1 - strlen(#linebuf) * list.font_w + left_gap;
}
}
}
void TWebBrowser::tag_hr()
{
dword hrcol = 0x00777777;
dword hr_width = draw_w-BODY_MARGIN-BODY_MARGIN;
dword hr_size = 1;
if (tag.get_value_of("color")) {
hrcol = GetColor(tag.value);
}
if (tag.get_value_of("width")) && (!strchr(tag.value, '%')) {
hr_width = math.min(hr_width, tag.get_number_of("width"));
}
if (tag.get_number_of("size")) {
hr_size = math.min(500, tag.number);
}
if (draw_x != left_gap) NewLine();
if (secondrun) canvas.DrawBar(left_gap, style.cur_line_h / 2 + draw_y - 1, hr_width, hr_size, hrcol);
draw_y += hr_size - 3;
draw_x++;
NewLine();
return;
}
void TWebBrowser::tag_body()
{
t_body = tag.opened;
if (tag.get_value_of("link")) link_color_default = GetColor(tag.value);
if (tag.get_value_of("alink")) link_color_active = GetColor(tag.value);
if (tag.get_value_of("text")) text_colors.set(0, GetColor(tag.value));
if (tag.get_value_of("bgcolor")) bg_colors.set(0, GetColor(tag.value));
// Autodetecting encoding if no encoding was set
if (tag.opened) && (custom_encoding==-1) && (cur_encoding == CH_CP866) {
if (strstr(bufpointer, "\208\190")) ChangeEncoding(CH_UTF8);
else if (chrnum(bufpointer, '\246')>5) ChangeEncoding(CH_CP1251);
}
}
void TWebBrowser::tag_q()
{
chrncat(#linebuf, '\"', sizeof(TWebBrowser.linebuf));
}
void TWebBrowser::reset_font_style()
{
list.SetFont(BASIC_CHAR_W, 14, 10011000b);
style.cur_line_h = list.item_h = list.font_h + 5;
}
void TWebBrowser::tag_h1234_caption()
{
if (ESBYTE[#tag.name+1]=='4') {
NewLine();
NewLine();
style.h = tag.opened;
style.b = tag.opened;
} else {
style.h = tag.opened;
if (tag.opened) {
if (!style.pre) {
NewLine();
NewLine();
}
if (tag.is("h1")) {
list.SetFont(BASIC_CHAR_W*2, 14+13, 10011001b);
style.b = true;
} else if (tag.is("h2")) {
list.SetFont(BASIC_CHAR_W*2, 14+13, 10011001b);
} else {
list.SetFont(6*2, 9+8, 10001001b);
}
style.cur_line_h = list.item_h = list.font_h + 3;
} else {
if (tag.is("h1")) style.b = false;
NewLine();
reset_font_style();
}
}
}
void TWebBrowser::tag_kosicon()
{
dword imgbuf[44];
dword maxicon;
dword shared_i18 = memopen("ICONS18", NULL, SHM_READ);
maxicon = EDX / 18 / 18 / 4;
if (shared_i18) && (tag.get_number_of("n")) {
if (tag.number < maxicon) {
if (draw_x + 18 > canvas.bufw) NewLine();
canvas.DrawImage(draw_x, draw_y-1, 18, 18, 18*18*4*tag.number+shared_i18);
draw_x += 22;
}
}
}
void TWebBrowser::tag_img()
{
char img_path[4096]=0;
dword base64img;
if (!tag.get_value_of("data-large-image"))
if (!tag.get_value_of("data-src"))
if (!tag.get_value_of("src")) return;
if (streqrp(tag.value, "data:")) {
if (!strstr(tag.value, "base64,")) goto NOIMG;
EDX = EAX+7;
if (ESBYTE[EDX]==' ') EDX++;
base64img = malloc(strlen(EDX));
base64_decode stdcall (EDX, base64img, strlen(EDX));
img_decode stdcall (base64img, EAX, 0);
$push eax
free(base64img);
$pop eax
if (EAX) goto IMGOK; else goto NOIMG;
}
if (!strcmp(tag.value + strrchr(tag.value, '.'), "svg")) goto NOIMG;
if (!strcmp(tag.value + strrchr(tag.value, '.'), "webp")) goto NOIMG;
strlcpy(#img_path, tag.value, sizeof(img_path)-1);
replace_char(#img_path, ' ', '\0', sizeof(img_path)-1);
get_absolute_url(#img_path, history.current());
if (check_is_the_adress_local(#img_path)) {
img_from_file stdcall(#img_path);
if (EAX) goto IMGOK; else goto NOIMG;
}
if (cache.has(#img_path)) {
img_decode stdcall (cache.current_buf, cache.current_size, 0);
if (EAX) goto IMGOK; else goto NOIMG;
} else {
if (img_url.get_pos_by_name(#img_path)==-1) img_url.add(#img_path);
goto NOIMG;
}
IMGOK:
if (RenderImage(EAX)) return;
NOIMG:
if (tag.get_value_of("title")) || (tag.get_value_of("alt")) {
strncpy(#img_path, tag.value, sizeof(TWebBrowser.linebuf)-3);
sprintf(#linebuf, "[%s]", #img_path);
} else {
if (streqrp(#img_path, "data:")) img_path=0;
replace_char(#img_path, '?', NULL, strlen(#img_path));
img_path[sizeof(TWebBrowser.linebuf)-3] = '\0'; //prevent overflow in sprintf
sprintf(#linebuf, "[%s]", #img_path+strrchr(#img_path, '/'));
linebuf[50]= NULL;
}
text_colors.add(0x9A6F29);
style.image = true;
RenderTextbuf();
style.image = false;
text_colors.pop();
}
struct TABLE {
int depth;
int margin;
collection_int cols;
} table;
unsigned table_id;
unsigned colcount;
unsigned tr_pos;
unsigned td_pos;
unsigned row_start_y;
unsigned tallest_cell_in_row;
unsigned cur_cell_w;
void TWebBrowser::tag_table_reset()
{
table_id = 0;
colcount = 0;
tr_pos = 0;
td_pos = 0;
table.depth = 0;
cur_cell_w = 0;
}
void TWebBrowser::tag_table()
{
if (!tag.opened) {
if (style.font) tag_font();
if (link) tag_a();
style.b = false;
}
if (tag.is("table")) {
if(tag.opened) {
table.depth++;
if (table.depth==1) {
table_id++;
colcount = 0;
td_pos = 0;
row_start_y = draw_y;
if (tag.get_number_of("width")) {
if (strchr(tag.value, '%')) tag.number = list.w * tag.number / 100;
cur_cell_w = math.min(tag.number,list.w);
} else {
cur_cell_w = list.w;
}
}
} else {
if (table.depth>0) {
table.depth--;
}
if (table.depth==0) {
draw_x = left_gap = style.tag_list.level * 5 * list.font_w + BODY_MARGIN;
draw_w = list.w;
if (td_pos) draw_y = math.max(draw_y, tallest_cell_in_row);
draw_y = math.max(draw_y+style.cur_line_h, tallest_cell_in_row);
row_start_y = tallest_cell_in_row = draw_y;
style.cur_line_h = list.item_h;
}
}
}
if (table.depth>1) {
if (tag.is("tr")) && (tag.opened) NewLine();
return;
}
if (!secondrun) {
if (tag.is("tr")) {
if (tag.opened) {
table.cols.add(1);
}
colcount = 0;
}
if (tag.opened) if (tag.is("td")) || (tag.is("th")) {
if (!table.cols.count) { table.cols.add(1); colcount = 0;}
colcount++;
if (colcount) table.cols.set(table.cols.count-1, colcount);
//if (tag.get_number_of("colspan")) colcount += tag.number-1;
}
} else {
if (tag.is("tr")) {
if (tag.opened) {
if (td_pos) draw_y = math.max(draw_y, tallest_cell_in_row);
_TR_FIX:
if (draw_x==left_gap) && (draw_y==BODY_MARGIN) {
row_start_y = tallest_cell_in_row = draw_y;
} else {
row_start_y = tallest_cell_in_row = draw_y = draw_y + style.cur_line_h;
}
style.cur_line_h = list.item_h;
tr_pos++;
td_pos = 0;
} else {
draw_y = math.max(draw_y, tallest_cell_in_row);
td_pos = 0;
}
draw_x = left_gap = style.tag_list.level * 5 * list.font_w + BODY_MARGIN;
draw_w = list.w;
}
if (tag.is("td")) || (tag.is("th")) {
if (!tr_pos) goto _TR_FIX;
tallest_cell_in_row = math.max(draw_y+style.cur_line_h-list.item_h+1, tallest_cell_in_row);
style.cur_line_h = list.item_h;
if (tag.opened)
{
if (!td_pos) {
table.margin = list.w - cur_cell_w / 2 + BODY_MARGIN;
draw_x = left_gap = table.margin;
draw_w = cur_cell_w - BODY_MARGIN;
} else {
draw_x = left_gap = left_gap + draw_w;
draw_w = cur_cell_w - left_gap + table.margin - BODY_MARGIN;
}
if (EAX = table.cols.get(tr_pos-1)-td_pos) {
draw_w /= EAX;
} else {
draw_y = row_start_y;
draw_x = left_gap = table.margin;
}
if (table.cols.get(tr_pos-1)-td_pos>1) && (tag.get_number_of("width")) {
if (strchr(tag.value, '%')) {
tag.number = cur_cell_w * tag.number / 100; //
}
if (tag.number < list.w - table.margin - left_gap) draw_w = tag.number;
}
draw_y = row_start_y;
td_pos++;
}
}
}
if (draw_x > cur_cell_w) {
draw_x = left_gap = table.margin;
draw_w = cur_cell_w - table.margin - 23 - left_gap;
table.depth = 0;
NewLine();
if (debug_mode) {
debugln("anomaly draw_x");
canvas.DrawBar(0, draw_y, 20, 20, 0xFF0000);
}
}
//if (left_gap + draw_w > list.w) {
// draw_w = list.w - left_gap;
// if (debug_mode) debugln("anomaly draw_W");
//}
}
+117
View File
@@ -0,0 +1,117 @@
char *unicode_symbols[]={
"quot","\"",
"amp", "&",
"lt", "<",
"gt", ">",
"#183","\31", "middot", "\31",
"#149","-",
"#151","-",
"#160"," ", "nbsp", "\t", "emsp", " ",
"#169","(c)", "copy", "(c)",
"#171","<<", "laquo","<<",
"#174","(r)", "reg", "(r)",
"#187",">>", "raquo",">>",
"hellip", "...",
"trade", "[TM]",
"bdquo", ",,",
"minus", "-",
"ndash", "-",
"mdash", "-", //--
"rsquo", "'", "apos", "'",
"sect", "#",
"ensp", " ",
"emsp13", " ",
"emsp14", " ",
"numsp", " ",
"puncsp", " ",
"thinsp", " ",
"#1028", "\242",
"#1030", "I",
"#1031", "\244",
"#8211", "-",
"#8212", "-",
"#8217", "'",
"#8220", "\"",
"#8222", "\"", "ldquo", "\"",
"#8221", "\"", "rdquo", "\"",
"#8470", "N",
"#8722", "-",
"#9642", "-", //square in the middle of the line
"#9658", ">",
"#9660", "v",
"#10094", "<",
"#10095", ">",
"#65122", "+",
"#8594", "->",
"#8627", "->",
"uarr", "^",
"darr", "v",
"rarr", "->",
"larr", "<-",
"bull", "\31",
"percnt","%",
"#xfeff", "",
"times", "x",
"lowast","*",
"#128154","<3",
"#128545",":(",
0};
unsigned char unicode_chars[] = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяЁёhг\243i\105\244\0";
bool GetUnicodeSymbol(dword _line, line_size, bufpos, buf_end)
{
int i;
int code;
char special_code[10];
bool white_end = false;
dword bufstart = bufpos;
for (i=0; i<9; i++, bufpos++)
{
if (__isWhite(ESBYTE[bufpos])) {bufpos--; break;}
if (ESBYTE[bufpos] == ';') || (bufpos >= buf_end) break;
if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#", ESBYTE[bufpos])) {bufpos--; break;}
special_code[i] = ESBYTE[bufpos];
}
special_code[i] = '\0';
for (i=0; unicode_symbols[i]!=0; i+=2;)
{
if (!strcmp(#special_code, unicode_symbols[i]))
{
strncat(_line, unicode_symbols[i+1], line_size);
return bufpos;
}
}
if (special_code[0]=='#')
{
code = atoi(#special_code + 1);
if (code>=0) && (code<=255) {
chrncat(_line, code, line_size); //NOT ALL ASCII CODES IN KOLIBRI ARE COMPATABLE WITH STANDARDS
return bufpos;
}
if (code>=1040) && (code<=1040+72) {
chrncat(_line, unicode_chars[code-1040], line_size);
return bufpos;
}
}
chrncat(_line, '&', line_size);
return bufstart;
}
+38
View File
@@ -0,0 +1,38 @@
struct LIST
{
int level;
char ordered[5];
int counter[5];
void reset();
void upd_level();
int inc_counter();
char order_type();
};
void LIST::reset()
{
level = 0;
}
void LIST::upd_level(int direction, char type)
{
if (direction == 1) && (level<5) {
level++;
counter[level] = 0;
ordered[level] = type;
}
if (direction == 0) && (level>0) {
level--;
}
}
int LIST::inc_counter()
{
counter[level]++;
return counter[level];
}
char LIST::order_type()
{
return ordered[level];
}
+6
View File
@@ -0,0 +1,6 @@
if tup.getconfig("NO_CMM") ~= "" then return end
if tup.getconfig("LANG") == "ru_RU"
then C_LANG = "LANG_RUS"
else C_LANG = "LANG_ENG" -- this includes default case without config
end
tup.rule("WebView.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "WebView.com")
File diff suppressed because it is too large. Load diff
+17
View File
@@ -0,0 +1,17 @@
@ECHO OFF
@c-- /D=LANG_RUS WebView.c
@del WebView
@rename WebView.com WebView
@del warning.txt
if not exist WebView ( @pause )
if exist WebView (
"C:\Program Files (x86)\WinImage\winimage.exe" "C:\Users\leency\Desktop\kolibri.img" /H /Q /I WebView
d:
cd "D:\Kolibri\Infrastructure\QEMU"
call "C:\Users\leency\Desktop\qemu.bat"
) else (
pause
)
+1
View File
@@ -0,0 +1 @@
c-- -D=LANG_ENG WebView.c
+64
View File
@@ -0,0 +1,64 @@
enum {
PAGE=1, IMG, FILE
};
struct _cache
{
dword current_buf;
dword current_size;
dword current_type;
dword current_charset;
collection url;
collection_int data;
collection_int size;
collection_int type;
collection_int charset;
void add();
bool has();
void clear();
} cache;
void _cache::add(dword _url, _data, _size, _type, _charset)
{
dword data_pointer;
data_pointer = malloc(_size);
memmov(data_pointer, _data, _size);
data.add(data_pointer);
url.add(_url);
size.add(_size);
type.add(_type);
charset.add(_charset);
current_buf = data_pointer;
current_size = _size;
}
bool _cache::has(dword _link)
{
int pos;
if (!url.count) return false;
pos = url.get_pos_by_name(_link);
if (pos != -1) {
current_buf = data.get(pos);
current_size = size.get(pos);
current_type = type.get(pos);
current_charset = charset.get(pos);
return true;
}
return false;
}
void _cache::clear()
{
int i;
for (i=0; i<data.count; i++) free(data.get(i));
url.drop();
data.drop();
size.drop();
type.drop();
current_buf = NULL;
current_size = NULL;
current_type = NULL;
current_charset = NULL;
}
+118
View File
@@ -0,0 +1,118 @@
#ifdef LANG_RUS
//===================================================//
// //
// CYRILLIC //
// //
//===================================================//
char buildin_page_error[] = FROM "res/page_not_found_ru.htm";
char buildin_page_home[] = FROM "res/homepage_ru.htm";
char buildin_page_help[] = FROM "res/help_ru.htm";
char accept_language[]= "Accept-Language: ru\n";
char rmb_menu[] =
"Back|Ctrl+<
Forward|Ctrl+>
-
Посмотреть исходник|Ctrl+U
Редактировать исходник|F2";
char main_menu[] =
"Открыть файл...|Ctrl+O
Новое окно|Ctrl+N
-
История|Ctrl+H
Менеджер загрузок|Ctrl+J
Настройки|Ctrl+E
Очистить кэш|Ctrl+F5
Обновить браузер";
char link_menu[] =
"Открыть в новой вкладке
Открыть в новом окне
-
Копировать ссылку
Скачать содержимое ссылки";
char loading_text[] = "Загрузка...";
char update_param[] = "-e http://builds.kolibrios.org/ru_RU/data/programs/cmm/browser/WebView.com";
char update_download_error[] = "'WebView\nОшибка при получении обновлений!' -tE";
char update_ok[] = "'WebView\nБраузер был успешно обновлен!' -tO";
char update_is_current[] = "'WebView\nВы уже используете последнюю версию.' -tI";
char update_can_not_copy[] = "'WebView\nНе могу переместить новую версию из папки Downloads на Ramdisk. Возможно, не достаточно места.' -tE";
char clear_cache_ok[] = "'WebView\nКэш очищен.' -tI";
#define T_RENDERING "Рендеринг страницы..."
#define T_DONE_IN_SEC "Готово: %i сек (%i милисек)"
#else
//===================================================//
// //
// ENGLISH //
// //
//===================================================//
char buildin_page_error[] = FROM "res/page_not_found_en.htm";
char buildin_page_home[] = FROM "res/homepage_en.htm";
char buildin_page_help[] = FROM "res/help_en.htm";
char accept_language[]= "Accept-Language: en\n";
char rmb_menu[] =
"Back|Ctrl+<
Forward|Ctrl+>
-
View source|Ctrl+U
Edit source|F2";
char main_menu[] =
"Open local file...|Ctrl+O
New window|Ctrl+N
-
History|Ctrl+H
Download Manager|Ctrl+J
Settings|Ctrl+E
Clear cache|Ctrl+F5
Update browser";
char link_menu[] =
"Open in new tab
Open in new window
-
Copy link
Download link contents";
char loading_text[] = "Loading...";
char update_param[] = "-e http://builds.kolibrios.org/en_US/data/programs/cmm/browser/WebView.com";
char update_download_error[] = "'WebView\nError receiving update information!' -tE";
char update_ok[] = "'WebView\nThe browser has been updated!' -tO";
char update_is_current[] = "'WebView\nThe browser is up to date.' -tI";
char update_can_not_copy[] = "'WebView\nError copying a new version from Downloads folder!\nProbably too litle space on Ramdisk.' -tE";
char clear_cache_ok[] = "'WebView\nThe cache has been cleared.' -tI";
#define T_RENDERING "Rendering..."
#define T_DONE_IN_SEC "Done in %i sec (%i milisec)"
#endif
//===================================================//
// //
// GLOBAL //
// //
//===================================================//
char buildin_page_test[] = FROM "res/test.htm";
#define URL_SERVICE_HISTORY "WebView:history"
#define URL_SERVICE_HOMEPAGE "WebView:home"
#define URL_SERVICE_TEST "WebView:test"
char webview_shared[] = "WEBVIEW";
enum {
NEW_TAB=600,
ENCODINGS=700,
BACK_BUTTON=800,
FORWARD_BUTTON, VIEW_SOURCE, EDIT_SOURCE,
REFRESH_BUTTON, GOTOURL_BUTTON, CHANGE_ENCODING,
GO_BUTTON, SEARCH_BUTTON, SANDWICH_BUTTON,
OPEN_FILE, NEW_WINDOW, VIEW_HISTORY, DOWNLOAD_MANAGER,
OPEN_SETTINGS, CLEAR_CACHE, UPDATE_BROWSER, IN_NEW_TAB, IN_NEW_WINDOW,
COPY_LINK_URL, DOWNLOAD_LINK_CT, TAB_ID,
TAB_CLOSE_ID = 900
};
char editbox_icons[] = FROM "res/editbox_icons.raw";
#define WIN_W 850
#define WIN_H 920
#define DEFAULT_URL URL_SERVICE_HOMEPAGE
char version[]="WebView 3.98";
+36
View File
@@ -0,0 +1,36 @@
#ifdef LANG_RUS
#define HISTORY_HEADER "<html><title>История</title><body bgcolor=#fff><h3>Посещенные страницы</h3><br>"
#else
#define HISTORY_HEADER "<html><title>History</title><body bgcolor=#fff><h3>Visited pages</h3><br>"
#endif
ShowHistory()
{
int i;
dword history_pointer = malloc(history.items.data_size+256);
strcat(history_pointer, HISTORY_HEADER);
for (i=0; i<history.items.count-1; i++) //if (cache.type.get(i) == PAGE)
{
strcat(history_pointer, "<kosicon n=3><a href='");
strcat(history_pointer, history.items.get(i));
strcat(history_pointer, "'>");
strcat(history_pointer, history.items.get(i));
strcat(history_pointer, "</a><br>");
}
/*
strcat(history_pointer, "<br><b>Cached images</b><br>");
for (i=1; i<cache.url.count; i++) if (cache.type.get(i) == IMG)
{
strcat(history_pointer, cache.url.get(i));
strcat(history_pointer, " <img src='");
strcat(history_pointer, cache.url.get(i));
strcat(history_pointer, "'><br>");
}
*/
LoadInternalPage(history_pointer, strlen(history_pointer));
free(history_pointer);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1 @@
                                                                                                                                                                                                                                                                                                                                                                                 ▐▐▌бЯЮВБ~xwtВБ~бЯЮ▐▐▌      ╜╗╗                                 ¤¤¤млк{xuЙЕГСОМЦУССОМЙЕГ{xuмлл╗╗╣rpm                                 нмй~{ПНКЙЕГ~{x{xu|yЙЕГПНККЖДЙЕГxvs                              ▐▐▌{xuПНКБ|ввЯччх√√√ччхеввКИДЩХТЩХТyxu                              вЯЯЙЕГЙЕГввЯ            ╛╜╗КЖДЩХТЩХТyxu                              ГБСОМ~{xччх         ╜╗╗rpmxvsyxuyxutqo                              xwtЦУС{xu···                                                         ДБСОМ~{xшчч                                                         бЮЭЙЕГЙЕГдба               пон}yx┤│▓                                 ▌▌▌{xuПНКБ|двбччч√√√чччдвб~{ЙЕГ|yv                                    нкк~{ПНКЙЕГ~{x{xu~{xЙЕГПНК~{нлй                                    √√√нкк{xuЙЕГСОМЦУССОМЙЕГ{xuнкк№№№                                          ▐▌▌вЯЯВБxwtВБвЯЯ▐▌▌                                                                                                                                                                                                                                                                                                                                                                              ▄▄▄                                                                                                                                                                                                                                                                                                            ,╨                  ,╨                                          ,╨ФОъ,╨            ,╨ФОъ,╨                                    ,╨ФОъJA┘JA┘JA┘      JA┘ФОъJA┘JA┘,╨                              ,╨JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘,╨                            жJA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘,╨ ж                               жJA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘,╨ ж                                    ,╨JA┘JA┘JA┘JA┘JA┘JA┘JA┘,╨ ж                                          ,╨JA┘JA┘JA┘JA┘JA┘JA┘,╨                                          ,╨JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘ ж                                    ,╨ФОъJA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘JA┘,╨                              ,╨ФОъJA┘JA┘JA┘JA┘,╨,╨JA┘JA┘JA┘JA┘JA┘,╨                           ,╨JA┘JA┘JA┘JA┘,╨      ,╨JA┘JA┘JA┘,╨ ж                              ,╨JA┘,╨ ж            ,╨JA┘,╨ ж                                     ж ж                  ,╨ ж                                                                                                                                                                                                                                                                                                                                                                        ▄▄▄
+19
View File
@@ -0,0 +1,19 @@
<html><title>WebView Help</title><body>
<h1>WebView Text-Based Browser</h1>
It is free and open-source. If you have any suggestions or want to help improving it please visit its topic at <a href="//board.kolibrios.org/viewtopic.php?f=40&amp;t=1075">board.kolibrios.org</a><pre>
<b>Shortcut keys</b>
<font bg=C7CEE4>[CTRL + N or CTRL + T]</font> New window
<font bg=C7CEE4>[CTRL + R or F5]</font> Refresh the current page
<font bg=C7CEE4>[CTRL + O]</font> Start OpenDialog to open local file
<font bg=C7CEE4>[CTRL + U]</font> View a web page's source code
<font bg=C7CEE4>[CTRL + H]</font> Open browser history
<font bg=C7CEE4>[CTRL + J]</font> Display the file downloader
<font bg=C7CEE4>[CTRL + W]</font> Exit browser
<font bg=C7CEE4>[CTRL + ENTER]</font> Submit a web search
<font bg=C7CEE4>[CTRL + LEFT]</font> Back a page.
<font bg=C7CEE4>[CTRL + RIGHT]</font> Forward a page.
<font bg=C7CEE4>[F6]</font> Moves a text cursor to the omnibox
+17
View File
@@ -0,0 +1,17 @@
<html>
<meta charset="cp-866">
<title>Справка WebView</title>
<body><pre><h1>Справка WebView</h1>
<b>Клавиши быстрого вызова</b>
<font bg=C7CEE4>[CTRL + N или CTRL + T]</font> Новое окно
<font bg=C7CEE4>[CTRL + R или F5]</font> Перезагрузить страницу
<font bg=C7CEE4>[CTRL + O]</font> Вызвать диалог выбора файла
<font bg=C7CEE4>[CTRL + U]</font> Смотреть исходный код страницы
<font bg=C7CEE4>[CTRL + H]</font> Смотреть историю посещенных страниц
<font bg=C7CEE4>[CTRL + J]</font> Открыть загрузчик файлов
<font bg=C7CEE4>[CTRL + W]</font> Закрыть браузер
<font bg=C7CEE4>[CTRL + ENTER]</font> Поиск в интернете с помощью Google
<font bg=C7CEE4>[CTRL + ВЛЕВО]</font> Аналогично кнопке "Назад" в браузере
<font bg=C7CEE4>[CTRL + ВПРАВО]</font> Аналогично кнопке "Вперед"
<font bg=C7CEE4>[F6]</font> Перемещает текстовый курсор в омнибокс
+121
View File
@@ -0,0 +1,121 @@
enum { TAG, OPTION_VALUE, TEXT, COMMENT, INLINE_COMMENT, CODE };
char* C_HL_keywords[] = {
"switch", "if", "while", "for", "break", "continue", "return", "else",
"union", "typedef", "static", "class", "case", "#include",
"volatile", "register", "sizeof", "typedef", "union", "goto", "const", "auto",
"#define", "#endif", "#error", "#ifdef", "#ifndef", "#undef", "#if", "#else",
"inline",
"int ", "dword ", "long ", "double ", "float ", "char ", "unsigned ", "signed ",
"void ", "bool ", "enum ", "byte ", "word ", "struct ", "NULL", "loop", "stdcall ",
":void ", ":int ", ":bool ", ":dword ", NULL
};
dword ShowCodeSource(dword _bufpointer, _bufsize)
{
dword new_buf, new_buf_start, i;
int mode = CODE;
char spstr[64];
dword keylen;
dword keyn;
dword keycolor;
new_buf = malloc(_bufsize*10);
new_buf_start = new_buf;
sprintf(new_buf,"<html><head><title>%s</title><body><pre>",#current_path);
new_buf += strlen(new_buf);
for (i=_bufpointer; i<_bufpointer+_bufsize; i++)
{
if ('<' == ESBYTE[i]) {
strcpy(new_buf, "&lt;");
new_buf+=4;
continue;
}
if ('>' == ESBYTE[i]) {
strcpy(new_buf, "&gt;");
new_buf+=4;
continue;
}
if (ESBYTE[i] >= '0') && (ESBYTE[i] <= '9') && (CODE == mode) {
strcpy(new_buf, "<font color=#CF00FF>?</font>");
ESBYTE[new_buf+20] = ESBYTE[i];
new_buf+=28;
if (ESBYTE[i+1] == 'x') {
strcpy(new_buf, "<font color=#CF00FF>x</font>");
new_buf+=28;
i++;
}
continue;
}
if (CODE == mode) && ('\"' == ESBYTE[i]) {
mode = TEXT;
strcpy(new_buf, "<font color=#080>\"");
new_buf+=18;
continue;
}
if (TEXT == mode) && ('\"' == ESBYTE[i]) {
mode = CODE;
strcpy(new_buf, "\"</font>");
new_buf+=8;
continue;
}
if (! strncmp(i, "//", 2) ) && (mode == CODE) {
mode = INLINE_COMMENT;
strcpy(new_buf, "<font color=#999>//");
new_buf+=19;
i++;
continue;
}
if (INLINE_COMMENT == mode) {
if (13 == ESBYTE[i]) {
mode = CODE;
strcpy(new_buf, "\13</font>");
new_buf+=8;
continue;
}
}
if (! strncmp(i, "/*", 2) ) {
mode = COMMENT;
strcpy(new_buf, "<font color=#999>/*");
new_buf+=19;
i++;
continue;
}
if (! strncmp(i, "*/", 2) ) {
mode = CODE;
strcpy(new_buf, "*/</font>");
new_buf+=9;
i++;
continue;
}
if (CODE == mode) for (keyn=0; C_HL_keywords[keyn]!=NULL; keyn++)
{
keylen = strlen(C_HL_keywords[keyn]);
if (! strncmp(i, C_HL_keywords[keyn], keylen) ) {
if (keyn<31) keycolor="#f00"; else keycolor="#00f";
sprintf(#spstr, "<font color=%s>%s</font>", keycolor, C_HL_keywords[keyn]);
strcpy(new_buf, #spstr);
new_buf += keylen + 24;
i += keylen-1;
goto _CONTINUE;
}
}
ESBYTE[new_buf] = ESBYTE[i];
new_buf++;
_CONTINUE:
}
ESBYTE[new_buf] = 0;
LoadInternalPage(new_buf_start, new_buf - new_buf_start);
free(new_buf_start);
}
+49
View File
@@ -0,0 +1,49 @@
<html><head><title>New tab</title></head>
<body bgcolor=#fff>
<table><tr><td width=20><td width=220><pre>
_____________________
|# : : #|
| : WebView : |
| : for : |
| : KolibriOS : |
| : : |
| :_______________: |
| ____________ |
| | __ | |
| || | | |
\_____||__|________|__|<font color=#DDD>lc</font>
<font bg=#F8F15B> web <font bg=#FF5A7E color=#fff> 1.0 <font bg=#47D018> compatible
<font bg=#3CE7FF> </font></font></font></font>
<td>
</pre>
<kosicon n=58><a href=//kolibrios.org>Homepage</a> &nbsp;
<kosicon n=50><a href="//builds.kolibrios.org">Night-builds</a> &nbsp;
<kosicon n=50><a href="//ftp.kolibrios.org">FTP Server</a>
<pre>
By the way,
<font color="#555555">&bull; You can check for browser updates from the main menu.
&bull; To run a web search, type text in the address box and press Ctrl+Enter.
&bull; Pressing F6 moves the text cursor to the omnibox.
&bull; You can manually change the encoding of a page by clicking on the label in the bottom right corner.
~+
* +
' |
() .-.,="``"=. - o -
'=/_ \ |
* | '=.<a href=WebView:test>&nbsp;</a> |
\ `=./`, '
. '=.__.=' `=' *
+ +
O * ' .<font color=#DDD>jgs</font>
Loaded 100 of 635 files, more files were not shown because too many files have changed in this diff. Show more