diff --git a/web/components/devices.ts b/web/components/devices.ts index 9b24955..77d4989 100644 --- a/web/components/devices.ts +++ b/web/components/devices.ts @@ -207,7 +207,6 @@ class Devices extends Vue implements GenericDevices { rpc.dispatch(data); }; rpc.registerSignalHandler('log', (messages: any[]) => { - console.log(messages.join(' ')); writeMessage(messages); }); this.$set(this.devices[dev], 'worker', worker as WorkerExt); diff --git a/web/web-libusb/Cargo.lock b/web/web-libusb/Cargo.lock index da8dd7c..122e371 100644 --- a/web/web-libusb/Cargo.lock +++ b/web/web-libusb/Cargo.lock @@ -216,8 +216,6 @@ dependencies = [ [[package]] name = "libnspire-sys" version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361969d82d11a723a53ba4814d3086a7562812bc4cec8bd8b332fd478dc9c722" dependencies = [ "cc", "globwalk", diff --git a/web/web-libusb/Cargo.toml b/web/web-libusb/Cargo.toml index 8f025e4..3cb41a2 100644 --- a/web/web-libusb/Cargo.toml +++ b/web/web-libusb/Cargo.toml @@ -9,3 +9,4 @@ lto = true [patch.crates-io] libusb1-sys = { path = "web-libusb" } libc = { path = "wasm-libc" } +libnspire-sys = { path = "libnspire-sys" } diff --git a/web/web-libusb/libnspire-sys/Cargo.lock b/web/web-libusb/libnspire-sys/Cargo.lock new file mode 100644 index 0000000..ccc3a85 --- /dev/null +++ b/web/web-libusb/libnspire-sys/Cargo.lock @@ -0,0 +1,325 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "aho-corasick" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +dependencies = [ + "memchr", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bstr" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" +dependencies = [ + "memchr", +] + +[[package]] +name = "cc" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "filetime" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "globset" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9db17aec586697a93219b19726b5b68307eba92898c34b170857343fe67c99d" +dependencies = [ + "ignore", + "walkdir", +] + +[[package]] +name = "ignore" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22dcbf2a4a289528dbef21686354904e1c694ac642610a9bff9e7df730d9ec72" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "jobserver" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" + +[[package]] +name = "libflate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9bac9023e1db29c084f9f8cd9d3852e5e8fddf98fb47c4964a0ea4663d95949" +dependencies = [ + "adler32", + "crc32fast", + "libflate_lz77", + "rle-decode-fast", +] + +[[package]] +name = "libflate_lz77" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3286f09f7d4926fc486334f28d8d2e6ebe4f7f9994494b6dab27ddfad2c9b11b" + +[[package]] +name = "libnspire-sys" +version = "0.3.3" +dependencies = [ + "cc", + "globwalk", + "libusb1-sys", +] + +[[package]] +name = "libusb1-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f02e930161703cc97c0aab3a905feb9740db03a80910f31ab0f8fa309223f39" +dependencies = [ + "cc", + "libc", + "libflate", + "pkg-config", + "tar", + "vcpkg", +] + +[[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "pkg-config" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "regex" +version = "1.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" + +[[package]] +name = "rle-decode-fast" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "tar" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489997b7557e9a43e192c527face4feacc78bfbe6eed67fd55c4c9e381cba290" +dependencies = [ + "filetime", + "libc", + "redox_syscall", + "xattr", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "vcpkg" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" + +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] diff --git a/web/web-libusb/libnspire-sys/Cargo.toml b/web/web-libusb/libnspire-sys/Cargo.toml new file mode 100644 index 0000000..c68bf8b --- /dev/null +++ b/web/web-libusb/libnspire-sys/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "libnspire-sys" +description = "low-level FFI bindings to libnspire for USB interaction with TI Nspire calculators" +version = "0.3.3" +authors = ["lights0123 "] +edition = "2018" +build = "build.rs" +links = "nspire" +license = "GPL-3.0" +readme = "README.md" +repository = "https://github.com/lights0123/libnspire-rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libusb1-sys = "0.4.1" + +[build-dependencies] +cc = { version = "1.0", features = ["parallel"] } +globwalk = "0.7" +# bindgen = "0.55.1" diff --git a/web/web-libusb/libnspire-sys/README.md b/web/web-libusb/libnspire-sys/README.md new file mode 100644 index 0000000..89bbaf2 --- /dev/null +++ b/web/web-libusb/libnspire-sys/README.md @@ -0,0 +1,11 @@ +# libnspire-sys +[![Crates.io](https://img.shields.io/crates/v/libnspire-sys.svg)](https://crates.io/crates/libnspire-sys) +[![Docs.rs](https://docs.rs/libnspire-sys/badge.svg)](https://docs.rs/libnspire-sys) + +Low-level bindings to [libnspire] for USB interaction with TI Nspire calculators. + +## License + +WARNING: this crate is under the GPL-3.0, as that is what [libnspire] is under. + +[libnspire]: https://github.com/Vogtinator/libnspire diff --git a/web/web-libusb/libnspire-sys/build.rs b/web/web-libusb/libnspire-sys/build.rs new file mode 100644 index 0000000..7ed821b --- /dev/null +++ b/web/web-libusb/libnspire-sys/build.rs @@ -0,0 +1,44 @@ +use globwalk::DirEntry; + +fn main() { + let files = globwalk::GlobWalkerBuilder::from_patterns("libnspire/src", &["*.{c,cpp}"]) + .build() + .unwrap() + .into_iter() + .filter_map(Result::ok) + .map(DirEntry::into_path) + .inspect(|path| println!("cargo:rerun-if-changed={}", path.display())); + let mut cfg = cc::Build::new(); + if let Some(include) = std::env::var_os("DEP_USB_1.0_INCLUDE") { + cfg.include(include); + } + cfg.files(files) + .include("libnspire/src") + .include("libnspire/src/services") + .include("libnspire/src/api") + .compile("nspire"); + + // let bindings = bindgen::Builder::default() + // // The input header we would like to generate + // // bindings for. + // .header("libnspire/src/api/nspire.h") + // // Tell cargo to invalidate the built crate whenever any of the + // // included header files changed. + // .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // .whitelist_function("(nspire.*|free)") + // .whitelist_type("nspire.*") + // .whitelist_var("nspire.*") + // .whitelist_type("NSPIRE.*") + // .whitelist_var("NSPIRE.*") + // .rustified_enum("nspire_keys") + // .size_t_is_usize(true) + // // Finish the builder and generate the bindings. + // .generate() + // // Unwrap the Result and panic on failure. + // .expect("Unable to generate bindings"); + // + // // Write the bindings to the $OUT_DIR/bindings.rs file. + // bindings + // .write_to_file("src/bindings.rs") + // .expect("Couldn't write bindings!"); +} diff --git a/web/web-libusb/libnspire-sys/libnspire/AUTHORS b/web/web-libusb/libnspire-sys/libnspire/AUTHORS new file mode 100644 index 0000000..a94e063 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/AUTHORS @@ -0,0 +1,6 @@ +Daniel Tang +=========== + +Main developer + +tangrs@tangrs.id.au diff --git a/web/web-libusb/libnspire-sys/libnspire/COPYING b/web/web-libusb/libnspire-sys/libnspire/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/web/web-libusb/libnspire-sys/libnspire/README b/web/web-libusb/libnspire-sys/libnspire/README new file mode 100644 index 0000000..629ce10 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/README @@ -0,0 +1,27 @@ +============================== + Libnspire +============================== + +This is a library for communicating with TI-Nspire calculators. It was created as a lightweight alternative to the Nspire-specific functions in TiLP (http://lpg.ticalc.org/prj_tilp/index.html). The goal is to have a small library with a simple API and minimal dependancies. + +At the moment, it is still in need of polishing up and documentation needs writing. + +Dependancies +========== + +You will need: + + * libusb-1.0 + * pkg-config + +to build this library. + +Installing +========== + +To install: + + ./configure + make + make install + diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/devinfo.h b/web/web-libusb/libnspire-sys/libnspire/src/api/devinfo.h new file mode 100644 index 0000000..d140bdd --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/devinfo.h @@ -0,0 +1,99 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_DEVINFO_H +#define NSP_DEVINFO_H + +#include +#include "handle.h" + +enum nspire_battery { + NSPIRE_BATT_POWERED = 0x00, + NSPIRE_BATT_LOW = 0xF1, + NSPIRE_BATT_OK = 0x7F, + NSPIRE_BATT_UNKNOWN = 0xFF +}; + +enum nspire_version_index { + NSPIRE_VER_OS, + NSPIRE_VER_BOOT1, + NSPIRE_VER_BOOT2, + + /* Reserved */ + NSPIRE_VER_MAXNUM +}; + +enum nspire_type { + NSPIRE_CAS = 0x0E, + NSPIRE_NONCAS = 0x1E, + NSPIRE_CASCX = 0x0F, + NSPIRE_NONCASCX = 0x1F +}; + +enum nspire_runlevel { + NSPIRE_RUNLEVEL_RECOVERY = 1, + NSPIRE_RUNLEVEL_OS = 2 +}; + +struct nspire_devinfo { + /* Flash storage */ + struct { + uint64_t free, total; + } storage; + + /* Memory */ + struct { + uint64_t free, total; + } ram; + + /* Versions */ + struct { + uint8_t major, minor; + uint16_t build; + } versions[NSPIRE_VER_MAXNUM]; + enum nspire_type hw_type; + + /* Power */ + struct { + enum nspire_battery status; + uint8_t is_charging; + } batt; + uint8_t clock_speed; + + /* LCD */ + struct { + uint16_t width, height; + uint8_t bbp, sample_mode; + } lcd; + + /* File extensions */ + struct { + char file[8]; + char os[8]; + } extensions; + + /* ID */ + char device_name[20]; + char electronic_id[28]; + + /* Misc */ + enum nspire_runlevel runlevel; +}; + +int nspire_device_info(nspire_handle_t *handle, struct nspire_devinfo *i); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/dir.h b/web/web-libusb/libnspire-sys/libnspire/src/api/dir.h new file mode 100644 index 0000000..a6cde92 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/dir.h @@ -0,0 +1,50 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_DIR_H +#define NSP_DIR_H + +#include "file.h" +#include "handle.h" + +enum nspire_dir_type { + NSPIRE_FILE = 0, + NSPIRE_DIR = 1 +}; + +struct nspire_dir_item { + char name[240]; + uint64_t size, date; + enum nspire_dir_type type; +}; + +struct nspire_dir_info { + uint64_t num; + struct nspire_dir_item items[]; +}; + +int nspire_dirlist(nspire_handle_t *, const char *, struct nspire_dir_info **); +void nspire_dirlist_free(struct nspire_dir_info *d); +int nspire_dir_create(nspire_handle_t *handle, const char *path); +int nspire_dir_delete(nspire_handle_t *handle, const char *path); + +int nspire_attr(nspire_handle_t *, const char *, struct nspire_dir_item *); + +#define nspire_dir_move nspire_file_move +#define nspire_dir_rename nspire_file_move + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/error.h b/web/web-libusb/libnspire-sys/libnspire/src/api/error.h new file mode 100644 index 0000000..807a365 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/error.h @@ -0,0 +1,53 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_ERROR_H +#define NSP_ERROR_H + +enum { + NSPIRE_ERR_SUCCESS, + + /* Generic */ + NSPIRE_ERR_TIMEOUT, + NSPIRE_ERR_NOMEM, + NSPIRE_ERR_INVALID, + + /* USB */ + NSPIRE_ERR_LIBUSB, + NSPIRE_ERR_NODEVICE, + + /* Packet */ + NSPIRE_ERR_INVALPKT, + NSPIRE_ERR_NACK, + + /* Service */ + NSPIRE_ERR_BUSY, + + /* File/Dir services */ + NSPIRE_ERR_EXISTS, + NSPIRE_ERR_NONEXIST, + + /* OS install */ + NSPIRE_ERR_OSFAILED, + + /* Number of errors */ + NSPIRE_ERR_MAX +}; + +const char *nspire_strerror(int error); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/file.h b/web/web-libusb/libnspire-sys/libnspire/src/api/file.h new file mode 100644 index 0000000..c1cdf72 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/file.h @@ -0,0 +1,35 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_FILE_H +#define NSP_FILE_H + +#include +#include "handle.h" + +typedef void (*nspire_callback)(size_t, void*); +int nspire_file_write(nspire_handle_t *, const char *, void*, size_t, nspire_callback cb, void *cb_data); +int nspire_file_read(nspire_handle_t *handle, const char *path, + void* data, size_t size, size_t *read_bytes, nspire_callback cb, void *cb_data); +int nspire_file_move(nspire_handle_t *handle, const char *src, const char *dst); +int nspire_file_copy(nspire_handle_t *handle, const char *src, const char *dst); +int nspire_file_delete(nspire_handle_t *handle, const char *path); + +#define nspire_file_touch(h,p) nspire_file_write((h), (p), NULL, 0); +#define nspire_file_rename nspire_file_move + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/handle.h b/web/web-libusb/libnspire-sys/libnspire/src/api/handle.h new file mode 100644 index 0000000..566649d --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/handle.h @@ -0,0 +1,29 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_HANDLE_H +#define NSP_HANDLE_H + +#include + +typedef struct nspire_handle nspire_handle_t; +typedef struct libusb_device_handle libusb_device_handle; + +int nspire_init(nspire_handle_t **ptr, libusb_device_handle *dev, bool is_cx2); +void nspire_free(nspire_handle_t *ptr); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/key.h b/web/web-libusb/libnspire-sys/libnspire/src/api/key.h new file mode 100644 index 0000000..bf9f0ee --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/key.h @@ -0,0 +1,224 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_KEY_H +#define NSP_KEY_H + +#include +#include "handle.h" + +enum nspire_keys { + KEYNSP_ESC = 0x1B9600, + KEYNSP_CTRL_ESC = 0x00EF00, + KEYNSP_TAB = 0x099500, + KEYNSP_SHIFT_TAB = 0x7C9500, + KEYNSP_CTRL_TAB = 0x00ED00, + KEYNSP_HOME = 0x00FD00, + KEYNSP_CTRL_HOME = 0x00FE00, + KEYNSP_MENU = 0x003600, + KEYNSP_CTRL_MENU = 0x00CE00, + KEYNSP_MOUSE_CONTEXT_MENU = 0x00A000, + KEYNSP_CLICK = 0x00AD00, + KEYNSP_CTRL_CLICK = 0x00AC00, + KEYNSP_SHIFT_GRAB = 0x00F900, + KEYNSP_LEFT = 0x000700, + KEYNSP_SHIFT_LEFT = 0x00F100, + KEYNSP_SHIFT_HOLD_LEFT = 0x000703, + KEYNSP_CTRL_LEFT = 0x00DA00, + KEYNSP_RIGHT = 0x002700, + KEYNSP_SHIFT_RIGHT = 0x00F200, + KEYNSP_SHIFT_HOLD_RIGHT = 0x002703, + KEYNSP_CTRL_RIGHT = 0x00DB00, + KEYNSP_UP = 0x001700, + KEYNSP_SHIFT_UP = 0x00F300, + KEYNSP_SHIFT_HOLD_UP = 0x001703, + KEYNSP_CTRL_UP = 0x00DC00, + KEYNSP_DOWN = 0x003700, + KEYNSP_SHIFT_DOWN = 0x00F400, + KEYNSP_SHIFT_HOLD_DOWN = 0x003703, + KEYNSP_CTRL_DOWN = 0x00DD00, + KEYNSP_EQUAL = 0x3D7500, + KEYNSP_CTRL_EQUAL = 0x00E900, + KEYNSP_SUCH_THAT = 0x7CED00, + KEYNSP_A = 0x616600, + KEYNSP_SHIFT_A = 0x416600, + KEYNSP_CTRL_A = 0x616600, + KEYNSP_B = 0x624600, + KEYNSP_SHIFT_B = 0x424600, + KEYNSP_CTRL_B = 0x02B100, + KEYNSP_C = 0x632600, + KEYNSP_SHIFT_C = 0x432600, + KEYNSP_CTRL_C = 0x03B200, + KEYNSP_FLAG = 0x00A700, + KEYNSP_CTRL_FLAG = 0x00F800, + KEYNSP_LESS_THAN = 0x3CA600, + KEYNSP_CTRL_LESS_THAN = 0x00CF00, + KEYNSP_D = 0x648500, + KEYNSP_SHIFT_D = 0x448500, + KEYNSP_CTRL_D = 0x04B300, + KEYNSP_E = 0x656500, + KEYNSP_SHIFT_E = 0x456500, + KEYNSP_CTRL_E = 0x05B400, + KEYNSP_F = 0x664500, + KEYNSP_SHIFT_F = 0x464500, + KEYNSP_CTRL_F = 0x06B500, + KEYNSP_G = 0x672500, + KEYNSP_SHIFT_G = 0x472500, + KEYNSP_CTRL_G = 0x07B600, + KEYNSP_TILDE = 0x27F500, + KEYNSP_CTRL_TILDE = 0x240500, + KEYNSP_GREATER_THAN = 0x3E8600, + KEYNSP_CTRL_GREATER_THAN = 0x00DE00, + KEYNSP_H = 0x688400, + KEYNSP_SHIFT_H = 0x488400, + KEYNSP_CTRL_H = 0x08B700, + KEYNSP_I = 0x696400, + KEYNSP_SHIFT_I = 0x496400, + KEYNSP_CTRL_I = 0x09B800, + KEYNSP_J = 0x6A4400, + KEYNSP_SHIFT_J = 0x4A4400, + KEYNSP_CTRL_J = 0x0AB900, + KEYNSP_K = 0x6B2400, + KEYNSP_SHIFT_K = 0x4B2400, + KEYNSP_CTRL_K = 0x0BBA00, + KEYNSP_QUOTE = 0x22A100, + KEYNSP_IMAGINARY = 0x00A200, + KEYNSP_CTRL_IMAGINARY = 0x00A100, + KEYNSP_L = 0x6C8300, + KEYNSP_SHIFT_L = 0x4C8300, + KEYNSP_CTRL_L = 0x0CBB00, + KEYNSP_M = 0x6D6300, + KEYNSP_SHIFT_M = 0x4D6300, + KEYNSP_CTRL_M = 0x0DBC00, + KEYNSP_N = 0x6E4300, + KEYNSP_SHIFT_N = 0x4E4300, + KEYNSP_CTRL_N = 0x0EBD00, + KEYNSP_O = 0x6F2300, + KEYNSP_SHIFT_O = 0x4F2300, + KEYNSP_CTRL_O = 0x0FBE00, + KEYNSP_COLON = 0x3A0100, + KEYNSP_CTRL_COLON = 0x3B0200, + KEYNSP_EXP = 0x00A400, + KEYNSP_P = 0x708200, + KEYNSP_SHIFT_P = 0x508200, + KEYNSP_CTRL_P = 0x10BF00, + KEYNSP_Q = 0x716200, + KEYNSP_SHIFT_Q = 0x516200, + KEYNSP_CTRL_Q = 0x11C000, + KEYNSP_R = 0x724200, + KEYNSP_SHIFT_R = 0x524200, + KEYNSP_CTRL_R = 0x12C100, + KEYNSP_S = 0x732200, + KEYNSP_SHIFT_S = 0x532200, + KEYNSP_CTRL_S = 0x13C200, + KEYNSP_QUESTION_MARK = 0x3F0300, + KEYNSP_CTRL_QUESTION_MARK = 0x00CB00, + KEYNSP_PI = 0x00A300, + KEYNSP_CTRL_PI = 0x00F400, + KEYNSP_T = 0x748100, + KEYNSP_SHIFT_T = 0x548100, + KEYNSP_CTRL_T = 0x14C300, + KEYNSP_U = 0x756100, + KEYNSP_SHIFT_U = 0x556100, + KEYNSP_CTRL_U = 0x15C400, + KEYNSP_V = 0x764100, + KEYNSP_SHIFT_V = 0x564100, + KEYNSP_CTRL_V = 0x16C500, + KEYNSP_W = 0x772100, + KEYNSP_SHIFT_W = 0x572100, + KEYNSP_CTRL_W = 0x17C600, + KEYNSP_COMMA = 0x2CA000, + KEYNSP_THETA = 0x880600, + KEYNSP_X = 0x788000, + KEYNSP_SHIFT_X = 0x588000, + KEYNSP_CTRL_X = 0x18C700, + KEYNSP_Y = 0x796000, + KEYNSP_SHIFT_Y = 0x596000, + KEYNSP_CTRL_Y = 0x19C800, + KEYNSP_Z = 0x7A4000, + KEYNSP_SHIFT_Z = 0x5A4000, + KEYNSP_CTRL_Z = 0x1AC900, + KEYNSP_SPACE = 0x202000, + KEYNSP_CTRL_SPACE = 0x00CD00, + KEYNSP_NEW_LINE = 0x000A00, + KEYNSP_CTRL = 0x00AA04, + KEYNSP_SHIFT = 0x00AB03, + KEYNSP_CTRL_SHIFT = 0x00AB07, + KEYNSP_BACK_SPACE = 0x081500, + KEYNSP_SHIFT_BACK_SPACE = 0x081500, + KEYNSP_CTRL_BACK_SPACE = 0x00E304, + KEYNSP_VAR = 0x00AF00, + KEYNSP_CTRL_VAR = 0x00A800, + KEYNSP_LEFT_PARENTHESES = 0x285500, + KEYNSP_CTRL_LEFT_PARENTHESES = 0x00E700, + KEYNSP_RIGHT_PARENTHESES = 0x293500, + KEYNSP_CTRL_RIGHT_PARENTHESES = 0x00E500, + KEYNSP_CATALOG = 0x009100, + KEYNSP_CTRL_CATALOG = 0x00EE00, + KEYNSP_POWER = 0x5E9300, + KEYNSP_CTRL_POWER = 0x00EB00, + KEYNSP_SIN = 0x007400, + KEYNSP_CTRL_SIN = 0x00E800, + KEYNSP_COS = 0x005400, + KEYNSP_CTRL_COS = 0x00E600, + KEYNSP_TAN = 0x003400, + KEYNSP_CTRL_TAN = 0x00E400, + KEYNSP_SLASH = 0x2F1400, + KEYNSP_CTRL_SLASH = 0x00E200, + KEYNSP_SQUARE = 0x009300, + KEYNSP_CTRL_SQUARE = 0x009200, + KEYNSP_SEVEN = 0x377100, + KEYNSP_CTRL_SEVEN = 0x00D700, + KEYNSP_EIGHT = 0x385100, + KEYNSP_CTRL_EIGHT = 0x00D800, + KEYNSP_NINE = 0x393100, + KEYNSP_CTRL_NINE = 0x00D900, + KEYNSP_TIMES = 0x2A1300, + KEYNSP_CTRL_TIMES = 0x00E100, + KEYNSP_TEN_POWER = 0x00EC00, + KEYNSP_CTRL_TEN_POWER = 0x009400, + KEYNSP_FOUR = 0x347200, + KEYNSP_CTRL_FOUR = 0x00D400, + KEYNSP_FIVE = 0x355200, + KEYNSP_CTRL_FIVE = 0x00D500, + KEYNSP_SIX = 0x363200, + KEYNSP_CTRL_SIX = 0x00D600, + KEYNSP_MINUS = 0x2D1200, + KEYNSP_CTRL_MINUS = 0x00E000, + KEYNSP_E_POWER = 0x00CA00, + KEYNSP_CTRL_E_POWER = 0x00A900, + KEYNSP_ONE = 0x317300, + KEYNSP_CTRL_ONE = 0x00D100, + KEYNSP_TWO = 0x325300, + KEYNSP_CTRL_TWO = 0x00D200, + KEYNSP_THREE = 0x333300, + KEYNSP_CTRL_THREE = 0x00D300, + KEYNSP_PLUS = 0x2B1100, + KEYNSP_CTRL_PLUS = 0x00DF00, + KEYNSP_ON = 0x000B00, + KEYNSP_CTRL_ON = 0x00F000, + KEYNSP_ZERO = 0x305000, + KEYNSP_CTRL_ZERO = 0x00D000, + KEYNSP_POINT = 0x2E7000, + KEYNSP_NEG = 0xB13000, + KEYNSP_CTRL_NEG = 0x00AE00, + KEYNSP_ENTER = 0x0D1000, + KEYNSP_CTRL_ENTER = 0x00A600 +}; + +int nspire_send_key(nspire_handle_t *handle, uint32_t code); +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/nspire.h b/web/web-libusb/libnspire-sys/libnspire/src/api/nspire.h new file mode 100644 index 0000000..7b91d31 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/nspire.h @@ -0,0 +1,30 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_NSPIRE_H +#define NSP_NSPIRE_H + +#include "devinfo.h" +#include "key.h" +#include "dir.h" +#include "error.h" +#include "file.h" +#include "handle.h" +#include "os.h" +#include "screenshot.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/os.h b/web/web-libusb/libnspire-sys/libnspire/src/api/os.h new file mode 100644 index 0000000..f621225 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/os.h @@ -0,0 +1,27 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_OS_H +#define NSP_OS_H + +#include +#include "handle.h" + +typedef void (*nspire_callback)(size_t, void*); +int nspire_os_send(nspire_handle_t *handle, void* data, size_t size, nspire_callback cb, void *cb_data); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/api/screenshot.h b/web/web-libusb/libnspire-sys/libnspire/src/api/screenshot.h new file mode 100644 index 0000000..44ac2f4 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/api/screenshot.h @@ -0,0 +1,33 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef NSP_SCREENSHOT_H +#define NSP_SCREENSHOT_H + +#include +#include "handle.h" + +struct nspire_image { + uint16_t width, height; + uint8_t bbp; + + unsigned char data[]; +}; + +int nspire_screenshot(nspire_handle_t *handle, struct nspire_image **ptr); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/cx2.cpp b/web/web-libusb/libnspire-sys/libnspire/src/cx2.cpp new file mode 100644 index 0000000..25c6d36 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/cx2.cpp @@ -0,0 +1,486 @@ +/* + * This file is part of libnspire. + * + * libnspire is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libnspire is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libnspire. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "endianconv.h" +#ifdef _WIN32 +#include +#include +#include + +int gettimeofday(struct timeval *t, void *timezone) { + struct _timeb timebuffer; + _ftime( &timebuffer ); + t->tv_sec=timebuffer.time; + t->tv_usec=1000*timebuffer.millitm; + return 0; +} +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +#else +#include +#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#endif + +#include + +#include "cx2.h" +#include "error.h" +#include "packet.h" +// Windows... +#undef min + +enum Address { + AddrAll = 0xFF, + AddrMe = 0xFE, + AddrCalc = 0x01 +}; + +enum Service { + AddrReqService = 0x01, + TimeService = 0x02, + EchoService = 0x03, + StreamService = 0x04, + TransmitService = 0x05, + LoopbackService = 0x06, + StatsService = 0x07, + UnknownService = 0x08, + AckFlag = 0x80 +}; + +// Big endian! +PACK(struct NNSEMessage { + uint8_t misc; // Unused? + uint8_t service; // Service number. If bit 7 set, an ACK + uint8_t src; // Address of the source + uint8_t dest; // Address of the destination + uint8_t unknown; // No idea + uint8_t reqAck; // 0x1: Whether an ack is expected, 0x9: Not the first try + uint16_t length; // Length of the packet, including this header + uint16_t seqno; // Sequence number. Increases by one for every non-ACK packet. + uint16_t csum; // Checksum. Inverse of the 16bit modular sum with carry added. +}); + +PACK(struct NNSEMessage_AddrReq { + NNSEMessage hdr; + uint8_t code; // 00 + uint8_t clientID[64]; +}); + +PACK(struct NNSEMessage_AddrResp { + NNSEMessage hdr; + uint8_t addr; +}); + +PACK(struct NNSEMessage_UnkResp { + NNSEMessage hdr; + uint8_t noidea[2]; // 80 03 +}); + +PACK(struct NNSEMessage_TimeReq { + NNSEMessage hdr; + uint8_t code; +}); + +PACK(struct NNSEMessage_TimeResp { + NNSEMessage hdr; + uint8_t noidea; // 80 + uint32_t sec; + uint64_t frac; + uint32_t frac2; +}); + +static uint8_t *getPacketData(const NNSEMessage *c) { + return ((uint8_t *)c) + sizeof(NNSEMessage); +} + +#ifdef DEBUG +static void dumpPacket(const NNSEMessage *message) +{ + printf("Misc: \t%02x\n", message->misc); + printf("Service:\t%02x\n", message->service); + printf("Dest: \t%02x\n", message->dest); + printf("Src: \t%02x\n", message->src); + printf("Unknown:\t%02x\n", message->unknown); + printf("ReqAck: \t%02x\n", message->reqAck); + printf("Length: \t%04x\n", ntohs(message->length)); + printf("SeqNo: \t%04x\n", ntohs(message->seqno)); + printf("Csum: \t%04x\n", ntohs(message->csum)); + + auto datalen = ntohs(message->length) - sizeof(NNSEMessage); + for(int i = 0; i < datalen; ++i) + printf("%02x ", getPacketData(message)[i]); + + printf("\n"); +} +#endif + +static uint16_t compute_checksum(const uint8_t *data, uint32_t size) +{ + uint32_t acc = 0; + + if (size > 0) + { + for (uint32_t i = 0; i < size - 1; i += 2) + { + uint16_t cur = (((uint16_t)data[i]) << 8) | data[i + 1]; + acc += cur; + } + + if (size & 1) + acc += (((uint16_t)data[size - 1]) << 8); + } + + while (acc >> 16) + acc = (acc >> 16) + uint16_t(acc); + + return acc; +} + +static bool readPacket(libusb_device_handle *handle, NNSEMessage *message, int maxlen) +{ + if(maxlen < sizeof(NNSEMessage)) + return false; + + int transferred = 0; + memset(message, 0, sizeof(NNSEMessage)); + int r = libusb_bulk_transfer(handle, 0x81, reinterpret_cast(message), maxlen, &transferred, 60000); + + if(r < 0 + || transferred < sizeof(NNSEMessage)) { + printf("%d %d %d", r, transferred, 5); + return false; + } + + const auto completeLength = ntohs(message->length); + + if(completeLength < sizeof(NNSEMessage) + || completeLength > maxlen) { + printf("complete %d", completeLength); + return false; + } + + uint8_t *data = reinterpret_cast(message) + transferred; + auto remainingLength = completeLength - transferred; + while(remainingLength > 0) + { + r = libusb_bulk_transfer(handle, 0x81, data, remainingLength, &transferred, 1000); + if(r < 0) { + printf("%d", r); + return false; + } + + data += transferred; + remainingLength -= transferred; + } + +#ifdef DEBUG + printf("Got packet:\n"); + dumpPacket(message); +#endif + + if(compute_checksum(reinterpret_cast(message), transferred) != 0xFFFF) + return false; + + return true; +} + +static bool writePacket(libusb_device_handle *handle, NNSEMessage *message) +{ + auto length = ntohs(message->length); + + message->csum = 0; + message->csum = htons(compute_checksum(reinterpret_cast(message), length) ^ 0xFFFF); + printf("comp"); + if(compute_checksum(reinterpret_cast(message), length) != 0xFFFF) + return false; + printf("comp done"); +//#ifdef DEBUG + printf("Sending packet:\n"); + dumpPacket(message); +//#endif + + int transferred = 0; + int r = libusb_bulk_transfer(handle, 0x01, reinterpret_cast(message), length, &transferred, 1000); + if(r < 0 + || length != transferred) + return false; + + return true; +} + +static uint16_t nextSeqno() +{ + static uint16_t seqno = 0; + return seqno++; +} + +template bool sendMessage(libusb_device_handle *handle, T &message) +{ + message.hdr.src = AddrMe; + message.hdr.dest = AddrCalc; + message.hdr.length = htons(sizeof(T)); + message.hdr.seqno = htons(nextSeqno()); + + return writePacket(handle, &message.hdr); +} + +template T* messageCast(NNSEMessage *message) +{ + if(ntohs(message->length) < sizeof(T)) + return nullptr; + + return reinterpret_cast(message); +} + +static void handlePacket(struct nspire_handle *nsp_handle, NNSEMessage *message, uint8_t **streamdata = nullptr, int *streamsize = nullptr) +{ + auto *handle = nsp_handle->device.dev; + + if(message->dest != AddrMe && message->dest != AddrAll) + { +#ifdef DEBUG + printf("Not for me?\n"); +#endif + return; + } + + if(message->service & AckFlag) + { +#ifdef DEBUG + printf("Got ack for %02x\n", ntohs(message->seqno)); +#endif + return; + } + + if(message->reqAck & 1) + { + NNSEMessage ack = {}; + ack.misc = message->misc; + ack.service = uint8_t(message->service | AckFlag); + ack.src = message->dest; + ack.dest = message->src; + ack.unknown = message->unknown; + ack.reqAck = uint8_t(message->reqAck & ~1); + ack.length = htons(sizeof(NNSEMessage)); + ack.seqno = message->seqno; + + if(!writePacket(handle, &ack)) + printf("Failed to ack\n"); + } + printf("%d", message->service); + switch(message->service & ~AckFlag) + { + case AddrReqService: + { + const NNSEMessage_AddrReq *req = messageCast(message); + if(!req || req->code != 0) + goto drop; + +#ifdef DEBUG + printf("Got request from client %s (product id %c%c)\n", &req->clientID[12], req->clientID[10], req->clientID[11]); +#endif + + NNSEMessage_AddrResp resp = {}; + resp.hdr.service = message->service; + resp.addr = AddrCalc; + + if(!sendMessage(handle, resp)) + printf("Failed to send message\n"); + + NNSEMessage_AddrResp resp2 = {}; + resp2.hdr.service = message->service; + resp2.addr = 0x80; // No idea + + if(!sendMessage(handle, resp2)) + printf("Failed to send message\n"); + + break; + } + case TimeService: + { + const NNSEMessage_TimeReq *req = messageCast(message); + if(!req || req->code != 0) + goto drop; + +#ifdef DEBUG + printf("Got time request\n"); +#endif + + struct timeval val; + gettimeofday(&val, nullptr); + + NNSEMessage_TimeResp resp = {}; + resp.hdr.service = message->service; + resp.noidea = 0x80; + resp.sec = htonl(uint32_t(val.tv_sec)); + resp.frac = 0; + + if(!sendMessage(handle, resp)) + printf("Failed to send message\n"); + + nsp_handle->cx2_handshake_complete = true; + break; + } + case UnknownService: + { + if(ntohs(message->length) != sizeof(NNSEMessage) + 1 || getPacketData(message)[0] != 0x01) + goto drop; + +#ifdef DEBUG + printf("Got packet for unknown service\n"); +#endif + + NNSEMessage_UnkResp resp = {}; + resp.hdr.service = message->service; + resp.noidea[0] = 0x81; + resp.noidea[1] = 0x03; + + if(!sendMessage(handle, resp)) + printf("Failed to send message\n"); + + break; + } + case StreamService: + { + if(streamdata) + *streamdata = getPacketData(message); + if(streamsize) + *streamsize = ntohs(message->length) - sizeof(NNSEMessage); + + break; + } + default: + printf("Unhandled service %02x\n", message->service & ~AckFlag); + } + + return; + + drop: + printf("Ignoring packet.\n"); +} + +static bool assureReady(struct nspire_handle *nsp_handle) +{ + if(nsp_handle->cx2_handshake_complete) + return true; + + auto *handle = nsp_handle->device.dev; + + const int maxlen = sizeof(NNSEMessage) + 1472; + NNSEMessage * const message = reinterpret_cast(malloc(maxlen)); + printf("begin loop"); + for(int i = 10; i-- && !nsp_handle->cx2_handshake_complete;) + { + printf("looping partially"); + if(!readPacket(handle, message, maxlen)) { + printf("cont"); + continue; + } + + handlePacket(nsp_handle, message); + } + free(message); + + return nsp_handle->cx2_handshake_complete; +} + +int packet_send_cx2(struct nspire_handle *nsp_handle, char *data, int size) +{ + printf("packet_send_cx2"); + if(!assureReady(nsp_handle)) + return -NSPIRE_ERR_BUSY; + + auto *handle = nsp_handle->device.dev; + + int len = sizeof(NNSEMessage) + size; + NNSEMessage *msg = reinterpret_cast(malloc(len)); + + msg->service = StreamService; + msg->src = AddrMe; + msg->dest = AddrCalc; + msg->reqAck = 1; + msg->length = htons(len); + msg->seqno = htons(nextSeqno()); + + memcpy(getPacketData(msg), data, size); + + int ret = -NSPIRE_ERR_SUCCESS; + if(!writePacket(handle, msg)) { + printf("failed to write packet"); + ret = -NSPIRE_ERR_BUSY; + } else + { + const int maxlen = sizeof(NNSEMessage) + 1472; + NNSEMessage * const message = reinterpret_cast(malloc(maxlen)); + + bool acked = false; + for(int i = 10; i-- && !ret && !acked;) + { + if(!readPacket(handle, message, maxlen)) + continue; + + handlePacket(nsp_handle, message); + + if(message->dest == AddrMe + && message->service == (StreamService | AckFlag) + && message->seqno == msg->seqno) + acked = true; + } + + if(!acked) + ret = -NSPIRE_ERR_BUSY; + + free(message); + } + + free(msg); + + return ret; +} + +int packet_recv_cx2(struct nspire_handle *nsp_handle, char *data, int size) +{ + if(!assureReady(nsp_handle)) + return -NSPIRE_ERR_BUSY; + + auto *handle = nsp_handle->device.dev; + + const int maxlen = sizeof(NNSEMessage) + 1472; + NNSEMessage * const message = reinterpret_cast(malloc(maxlen)); + + uint8_t *streamdata = nullptr; + int streamsize = 0; + for(int i = 10; i-- && !streamdata;) + { + if(!readPacket(handle, message, maxlen)) + continue; + + handlePacket(nsp_handle, message, &streamdata, &streamsize); + } + + if(streamdata) + memcpy(data, streamdata, std::min(size, streamsize)); + + free(message); + + return streamdata ? -NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_INVALPKT; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/cx2.h b/web/web-libusb/libnspire-sys/libnspire/src/cx2.h new file mode 100644 index 0000000..a64e51f --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/cx2.h @@ -0,0 +1,43 @@ +/* + * This file is part of libnspire. + * + * libnspire is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libnspire is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libnspire. If not, see . + */ + +#ifndef CX2_H +#define CX2_H + +#ifdef _WIN32 +#include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct nspire_handle; + +// Receive a NavNet packet wrapped in the NavNet SE protocol. +// Takes care of the handshake and other NNSE stuff like acking. +int packet_recv_cx2(struct nspire_handle *handle, char *data, int size); +// Send a NavNet packet wrapped in the NavNet SE protocol and wait for an ack. +// Takes care of the handshake and other NNSE stuff like acking. +int packet_send_cx2(struct nspire_handle *handle, char *data, int size); + +#ifdef __cplusplus +} +#endif + +#endif // CX2_H diff --git a/web/web-libusb/libnspire-sys/libnspire/src/data.c b/web/web-libusb/libnspire-sys/libnspire/src/data.c new file mode 100644 index 0000000..5243aa0 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/data.c @@ -0,0 +1,383 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include +#include + +#include "endianconv.h" +#include "error.h" +#include "packet.h" +#include "handle.h" + +static int handle_unknown(nspire_handle_t *handle, struct packet p) { + int ret; + + switch (p.dst_sid) { + case 0x40de: /* Disconnection */ + ret = packet_ack(handle, p); + break; + default: + ret = packet_nack(handle, p); + break; + } + return ret; +} + +int data_write_special(nspire_handle_t *handle, void *ptr, size_t len, + void (*packet_callback)(struct packet *p)) { + int ret; + struct packet p = packet_new(handle); + + if(len < 0xFF) { + memcpy(p.data, ptr, len); + p.data_size = len; + } else if(len <= packet_max_datasize(handle)) { + memcpy(p.bigdata, ptr, len); + p.bigdatasize = dcpu32(len); + p.data_size = 0xFF; + } else + return NSPIRE_ERR_NOMEM; + + if (packet_callback) + packet_callback(&p); + + if ((ret = packet_send(handle, p))) + return ret; + + // Acks are handled a level lower only, in packet_send + if (handle->is_cx2) + return NSPIRE_ERR_SUCCESS; + + /* + * Wait for an ACK packet while also NACKing spurious packets (like + * the LOGIN request). + * + * Legitimate packets that need ACKing will be resent by the device + * ready for reading in the next data_read call + */ + while (1) { + if ( (ret = packet_recv(handle, &p)) ) + return ret; + + if (p.dst_sid == handle->host_sid) { + if ((p.src_sid == 0xFF || p.src_sid == 0xFE)) { + handle->seq++; + if (!handle->seq) handle->seq++; + return NSPIRE_ERR_SUCCESS; + } else + if (p.src_sid == 0xD3) { + return -NSPIRE_ERR_INVALPKT; + } + } else { + handle_unknown(handle, p); + } + } +} + +int data_write(nspire_handle_t *handle, void *ptr, size_t len) { + return data_write_special(handle, ptr, len, NULL); +} + +int data_read(nspire_handle_t *handle, void *ptr, size_t maxlen, size_t *actual) { + int ret; + size_t len; + struct packet p; + + while (1) { + if ( (ret = packet_recv(handle, &p)) ) + return ret; + + if (p.dst_sid == handle->host_sid) { + // Acks are handled a level lower only, in packet_recv + if(handle->is_cx2) + break; + + if ( (ret = packet_ack(handle, p)) ) + return ret; + break; + } else { + handle_unknown(handle, p); + } + + if (ret) + return ret; + } + + len = (maxlen < packet_datasize(&p)) ? maxlen : packet_datasize(&p); + memcpy(ptr, packet_dataptr(&p), len); + + if(actual) + *actual = len; + + return NSPIRE_ERR_SUCCESS; +} + +/* + Format string: + b 8 bit integer + h 16 bit integer + w 32 bit integer + l 64 bit integer + 0 expect zero + s null terminated string len >= 8 + S null terminated string +*/ + +int data_scan(const char *format, const void *buffer, size_t len, ...) { + int ret; + const uint8_t *ptr = buffer, *end = ptr + len; + va_list ap; + + va_start(ap, len); + while (ptr < end && *format) { + len = end - ptr; + switch (*format) { + case 'b': + { + uint8_t *in = va_arg(ap, uint8_t*); + if (in) *in = *ptr; + ptr++; + break; + } + case 'h': + { + uint16_t *in = va_arg(ap, uint16_t*); + if (len < 2) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + if (in) { + *in = ptr[0]<<8 | ptr[1]; + } + ptr+=2; + break; + + } + case 'w': + { + uint32_t *in = va_arg(ap, uint32_t*); + if (len < 4) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + if (in) { + *in = ptr[0]<<24 | + ptr[1]<<16 | + ptr[2]<<8 | + ptr[3]; + } + ptr+=4; + break; + + } + case 'l': + { + uint64_t *in = va_arg(ap, uint64_t*); + if (len < 8) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + if (in) { + uint32_t low, high; + high = ptr[0]<<24 | + ptr[1]<<16 | + ptr[2]<<8 | + ptr[3]; + low = ptr[4]<<24 | + ptr[5]<<16 | + ptr[6]<<8 | + ptr[7]; + *in = ((uint64_t)high<<32) | low; + + } + ptr+=8; + break; + } + case 's': + { + char **in = va_arg(ap, char **); + uint8_t *next = memchr(ptr, '\0', len); + + if (!next) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + *in = (char*)ptr; + + /* Strings are padded with zeros until len >= 8 */ + /* Take this into account */ + if (next - ptr < 8) { + ptr = next + (8 - (next - ptr)); + } else { + ptr = next; + } + ptr++; + break; + } + case 'S': + { + char **in = va_arg(ap, char **); + uint8_t *next = memchr(ptr, '\0', len); + + if (!next) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + *in = (char*)ptr; + + ptr = next + 1; + break; + } + case '0': + if (*ptr != 0) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + ptr++; + break; + default: + ret = -NSPIRE_ERR_INVALID; + goto end; + } + format++; + } + + ret = NSPIRE_ERR_SUCCESS; +end: + va_end(ap); + return ret; +} + +int data_build(const char *format, void *buffer, + size_t len, size_t *wrote_bytes, ...) { + int ret; + uint8_t *ptr = buffer, *end = ptr + len; + va_list ap; + + va_start(ap, wrote_bytes); + while (ptr < end && *format) { + len = end - ptr; + switch (*format) { + case 'b': + { + uint8_t in = va_arg(ap, unsigned int); + *ptr = in; + ptr++; + break; + } + case 'h': + { + uint16_t in = va_arg(ap, unsigned int); + if (len < 2) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + ptr[0] = (in>>8) & 0xFF; + ptr[1] = (in) & 0xFF; + ptr+=2; + break; + + } + case 'w': + { + uint32_t in = va_arg(ap, uint32_t); + if (len < 4) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + ptr[0] = (in>>24) & 0xFF; + ptr[1] = (in>>16) & 0xFF; + ptr[2] = (in>>8) & 0xFF; + ptr[3] = (in) & 0xFF; + ptr+=4; + break; + + } + case 'l': + { + uint64_t in = va_arg(ap, uint64_t); + if (len < 8) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + ptr[0] = (in>>56) & 0xFF; + ptr[1] = (in>>48) & 0xFF; + ptr[2] = (in>>40) & 0xFF; + ptr[3] = (in>>32) & 0xFF; + ptr[4] = (in>>24) & 0xFF; + ptr[5] = (in>>16) & 0xFF; + ptr[6] = (in>>8) & 0xFF; + ptr[7] = (in) & 0xFF; + ptr+=8; + break; + } + case 's': + { + char *in = va_arg(ap, char *); + size_t strl = strlen(in); + + if (len <= strl || len <= 9) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + + /* Strings are padded with zeros until len (including the final 0) >= 9 */ + /* Take this into account */ + memset(ptr, 0, 9); + strncpy((char*)ptr, in, len); + + if (strl < 8) { + ptr += 8; + } else { + ptr += strl; + } + *ptr++ = '\0'; + break; + } + case 'S': + { + char *in = va_arg(ap, char *); + size_t strl = strlen(in); + + if (len <= strl) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + + strncpy((char*)ptr, in, len); + ptr += strl; + *ptr++ = '\0'; + break; + } + case '0': + *ptr++ = '\0'; + break; + default: + ret = -NSPIRE_ERR_INVALID; + goto end; + } + format++; + } + + if (wrote_bytes) + *wrote_bytes = ptr - (uint8_t*)buffer; + + ret = NSPIRE_ERR_SUCCESS; +end: + va_end(ap); + return ret; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/data.h b/web/web-libusb/libnspire-sys/libnspire/src/data.h new file mode 100644 index 0000000..6dace8c --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/data.h @@ -0,0 +1,43 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _DATA_H +#define _DATA_H + +#include +#include "handle.h" +#include "endianconv.h" +#include "packet.h" + +int data_write_special(nspire_handle_t*, void*, size_t, + void (*)(struct packet *)); + +int data_write(nspire_handle_t *handle, void *ptr, size_t maxlen); +int data_read(nspire_handle_t *handle, void *ptr, size_t maxlen, size_t *actual); +int data_build(const char *, void *, size_t, size_t *, ...); +int data_scan(const char *, const void *, size_t, ...); + +static inline int data_write8(nspire_handle_t *handle, uint8_t x) { + return data_write(handle, &x, 1); +} + +static inline int data_write16(nspire_handle_t *handle, uint16_t x) { + x = dcpu16(x); + return data_write(handle, &x, 2); +} + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/endianconv.h b/web/web-libusb/libnspire-sys/libnspire/src/endianconv.h new file mode 100644 index 0000000..e7b25dd --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/endianconv.h @@ -0,0 +1,32 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef ENDIANCONV_H +#define ENDIANCONV_H + +#ifdef _WIN32 +#include +#else +#include +#endif +#include + +#define dcpu16(x) htons(x) +#define dcpu32(x) htonl(x) +#define dcpu64(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/error.c b/web/web-libusb/libnspire-sys/libnspire/src/error.c new file mode 100644 index 0000000..b7fb79b --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/error.c @@ -0,0 +1,47 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include + +#include "error.h" + +static const char *error_msg[NSPIRE_ERR_MAX] = { + [NSPIRE_ERR_SUCCESS] = "No error", + [NSPIRE_ERR_TIMEOUT] = "Timeout", + [NSPIRE_ERR_NOMEM] = "Out of memory", + [NSPIRE_ERR_LIBUSB] = "Libusb error", + [NSPIRE_ERR_NODEVICE] = "No device found", + [NSPIRE_ERR_INVALPKT] = "Invalid packet received", + [NSPIRE_ERR_NACK] = "NACK received", + [NSPIRE_ERR_BUSY] = "Busy", + [NSPIRE_ERR_INVALID] = "Invalid input", + [NSPIRE_ERR_EXISTS] = "Already exists", + [NSPIRE_ERR_NONEXIST] = "Path does not exist", + +}; + +static const char* unknown_err = "Unknown error"; + +const char *nspire_strerror(int error) { + if (error > 0) + return unknown_err; + + if (error < -(sizeof(error_msg) / sizeof(const char*))) + return unknown_err; + + return error_msg[-error]; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/error.h b/web/web-libusb/libnspire-sys/libnspire/src/error.h new file mode 100644 index 0000000..858f870 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/error.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _ERROR_H +#define _ERROR_H + +#include "api/error.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/handle.h b/web/web-libusb/libnspire-sys/libnspire/src/handle.h new file mode 100644 index 0000000..f68ac80 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/handle.h @@ -0,0 +1,38 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _HANDLE_H +#define _HANDLE_H + +#include +#include + +#include "api/handle.h" +#include "usb.h" + +struct nspire_handle { + usb_device_t device; + + uint16_t host_addr, device_addr; + uint16_t host_sid, device_sid; + uint8_t seq, connected; + + bool is_cx2; + bool cx2_handshake_complete; +}; + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/init.c b/web/web-libusb/libnspire-sys/libnspire/src/init.c new file mode 100644 index 0000000..a3ff2f4 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/init.c @@ -0,0 +1,76 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include +#include + +#include "packet.h" +#include "error.h" +#include "usb.h" + +int nspire_init(nspire_handle_t **ptr, libusb_device_handle *dev, bool is_cx2) { + int ret; + struct packet p; + nspire_handle_t *h = malloc(sizeof(*h)); + + if (!h) + return -NSPIRE_ERR_NOMEM; + + if ( (ret = usb_init()) ) + goto error; + + h->is_cx2 = is_cx2; + if ( (ret = usb_get_device(&h->device, dev)) ) { + goto error; + } + + h->host_addr = 0x6400; + h->device_addr = 0x6401; + h->host_sid = 0x4003; + h->device_sid = 0x4003; + h->connected = 0; + h->seq = 1; + h->cx2_handshake_complete = false; + + if (!h->is_cx2) { + // Wait for an address request + if ( (ret = packet_recv(h, NULL)) ) + goto error_free_usb; + } + + p = packet_new(h); + packet_set_data(p, 0x64, 0x01, 0xFF, 0x00); + if ( (ret = packet_send(h, p)) ) + goto error_free_usb; + + h->host_sid = 0x8000; + + *ptr = h; + + return NSPIRE_ERR_SUCCESS; + +error_free_usb: + usb_free_device(&h->device); +error: + free(h); + return ret; +} + +void nspire_free(nspire_handle_t *ptr) { + usb_free_device(&ptr->device); + free(ptr); +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/init.h b/web/web-libusb/libnspire-sys/libnspire/src/init.h new file mode 100644 index 0000000..02d67c2 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/init.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _INIT_H +#define _INIT_H + +#include "handle.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/packet.c b/web/web-libusb/libnspire-sys/libnspire/src/packet.c new file mode 100644 index 0000000..1fb28c2 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/packet.c @@ -0,0 +1,225 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include +#include + +#include "cx2.h" +#include "handle.h" +#include "packet.h" +#include "error.h" +#include "usb.h" +#include "endianconv.h" + +#define PACKET_CONSTANT 0x54FD +#define HEADER_SIZE offsetof(struct packet, data) + +static uint8_t calculate_header_checksum(uint8_t *data, uint8_t size) { + uint8_t chksum = 0; + int i; + for (i=0; i>8; + chksum &= 0xFF; + tmp2 = (((chksum & 0xF) << 4) ^ chksum) << 8; + tmp3 = tmp2 >> 5; + chksum = tmp3 >> 7; + chksum ^= tmp1 ^ tmp2 ^ tmp3; + } + return chksum; +} + +static void fix_endian(struct packet *p) { + p->magic = dcpu16(p->magic); + p->src_addr = dcpu16(p->src_addr); + p->src_sid = dcpu16(p->src_sid); + p->dst_addr = dcpu16(p->dst_addr); + p->dst_sid = dcpu16(p->dst_sid); + p->data_checksum = dcpu16(p->data_checksum); +} + +static void finalize_packet(struct packet *p) { + p->magic = PACKET_CONSTANT; + + /* Calculate checksums */ + p->data_checksum = calculate_data_checksum(p->fulldata, packet_fulldatasize(p)); + p->header_checksum = calculate_header_checksum( + (uint8_t*)p, + HEADER_SIZE - 1 + ); + + /* Convert endian */ + fix_endian(p); +} + +static int is_header_valid(struct packet *p) { + uint8_t header_chksum = calculate_header_checksum( + (uint8_t*)p, + HEADER_SIZE - 1 + ); + + if (p->magic != PACKET_CONSTANT) return 0; + if (p->header_checksum != header_chksum) return 0; + return 1; +} + +static int is_data_valid(struct packet *p) { + uint16_t data_chksum = calculate_data_checksum(p->fulldata, packet_fulldatasize(p)); + if (!(p->data_checksum == data_chksum)) return 0; + return 1; +} + +#ifdef DEBUG +#include +static void dump_packet(const struct packet *p) { + printf( + "magic = %04x\n" + "src_addr = %04x\n" + "src_sid = %04x\n" + "dst_addr = %04x\n" + "dst_sid = %04x\n" + "data_chksm = %04x\n" + "size = %02x\n" + "ack = %02x\n" + "seq = %02x\n" + "hdr_chksm = %02x\n" + "data = ", + p->magic, + p->src_addr, + p->src_sid, + p->dst_addr, + p->dst_sid, + p->data_checksum, + p->data_size, + p->ack, + p->seq, + p->header_checksum); + + int i; + for (i=0; i<(packet_fulldatasize(p)); i++) { + printf("%02x ", p->fulldata[i]); + } + printf("\n"); +} +#endif + +int packet_send(nspire_handle_t *h, struct packet p) { + int size = HEADER_SIZE + packet_fulldatasize(&p); + +#ifdef DEBUG + printf("\nOUT ===>\n"); + dump_packet(&p); +#endif + + finalize_packet(&p); + if(h->is_cx2) { + printf("is cx2"); + return packet_send_cx2(h, (char*)&p, size); + } else + return usb_write(&h->device, (char*)&p, size); +} + +int packet_recv(nspire_handle_t *h, struct packet *p) { + int ret; + struct packet unused; + + /* if user passes in NULL, receive packet but ignore it */ + if (!p) + p = &unused; + + if(h->is_cx2) + ret = packet_recv_cx2(h, (char*)p, sizeof(*p)); + else + ret = usb_read(&h->device, p, sizeof(*p)); + + if (ret < 0) + return ret; + + fix_endian(p); + if (!is_header_valid(p) || !is_data_valid(p)) + return -NSPIRE_ERR_INVALPKT; + +#ifdef DEBUG + printf("\nIN <===\n"); + dump_packet(p); +#endif + + return -NSPIRE_ERR_SUCCESS; +} + +struct packet packet_new(nspire_handle_t *h) { + struct packet p = {0}; + + p.src_addr = h->host_addr; + p.dst_addr = h->device_addr; + p.src_sid = h->host_sid; + p.dst_sid = h->device_sid; + p.seq = h->is_cx2 ? 0 : h->seq; + + return p; +} + +static struct packet packet_new_ack(nspire_handle_t *h, struct packet p) { + struct packet ack = packet_new(h); + + ack.src_sid = p.seq ? 0xFF : 0xFE; + ack.dst_sid = p.src_sid; + + ack.seq = p.seq; + ack.ack = 0x0A; + + ack.data[0] = p.dst_sid>>8; + ack.data[1] = p.dst_sid&0xFF; + ack.data_size = 2; + + return ack; +} + +int packet_ack(nspire_handle_t *h, struct packet p) { + struct packet ack = packet_new_ack(h, p); + return packet_send(h, ack); +} + +int packet_nack(nspire_handle_t *h, struct packet p) { + struct packet nack = packet_new_ack(h, p); + nack.src_sid = 0xD3; + + return packet_send(h, nack); +} + +uint8_t *packet_dataptr(struct packet *p) { + return (p->data_size == 0xFF) ? p->bigdata : p->data; +} + +uint32_t packet_datasize(const struct packet *p) { + return (p->data_size == 0xFF) ? dcpu32(p->bigdatasize) : p->data_size; +} + +uint32_t packet_max_datasize(nspire_handle_t *h) { + return h->is_cx2 ? 1440 : 254; +} + +uint32_t packet_fulldatasize(const struct packet *p) { + return (p->data_size == 0xFF) ? (dcpu32(p->bigdatasize) + 4) : p->data_size; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/packet.h b/web/web-libusb/libnspire-sys/libnspire/src/packet.h new file mode 100644 index 0000000..cf207ef --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/packet.h @@ -0,0 +1,61 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _PACKET_H +#define _PACKET_H + +#include +#include "handle.h" + +struct packet { + uint16_t magic, + src_addr, + src_sid, + dst_addr, + dst_sid, + data_checksum; + uint8_t data_size, // If 0xFF, bigdata* counts + ack, + seq, + header_checksum; + union { + uint8_t data[254]; + struct { + uint32_t bigdatasize; + uint8_t bigdata[1440]; + }; + uint8_t fulldata[1444]; + }; +}; + +#define packet_set_data(p, ...) do { \ + unsigned char buffer[] = { __VA_ARGS__ }; \ + p.data_size = sizeof(buffer); \ + memcpy(p.data, buffer, p.data_size); \ + } while (0) + +int packet_send(nspire_handle_t *h, struct packet p); +int packet_recv(nspire_handle_t *h, struct packet *p); +struct packet packet_new(nspire_handle_t *h); +int packet_ack(nspire_handle_t *h, struct packet p); +int packet_nack(nspire_handle_t *h, struct packet p); +uint8_t *packet_dataptr(struct packet *p); +uint32_t packet_datasize(const struct packet *p); +uint32_t packet_fulldatasize(const struct packet *p); +uint32_t packet_max_datasize(nspire_handle_t *h); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/service.c b/web/web-libusb/libnspire-sys/libnspire/src/service.c new file mode 100644 index 0000000..0c0d30e --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/service.c @@ -0,0 +1,55 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include "error.h" +#include "data.h" +#include "packet.h" + +int service_connect(nspire_handle_t *handle, uint16_t sid) { + if (handle->connected) + return -NSPIRE_ERR_BUSY; + + handle->connected = 1; + handle->device_sid = sid; + + return NSPIRE_ERR_SUCCESS; +} + +static void mod_src(struct packet *p) { + p->src_sid = 0x40DE; +} + +int service_disconnect(nspire_handle_t *handle) { + int ret; + struct packet p; + uint8_t data[] = { + (handle->host_sid>>8) & 0xFF, + (handle->host_sid>>0) & 0xFF }; + + if (!handle->connected) + return NSPIRE_ERR_SUCCESS; + + p = packet_new(handle); + if ( (ret = data_write_special(handle, &data, 2, mod_src)) ) { + return ret; + } + + handle->connected = 0; + handle->host_sid++; + + return NSPIRE_ERR_SUCCESS; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/service.h b/web/web-libusb/libnspire-sys/libnspire/src/service.h new file mode 100644 index 0000000..6ceb493 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/service.h @@ -0,0 +1,27 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _SERVICE_H +#define _SERVICE_H + +#include +#include "handle.h" + +int service_connect(nspire_handle_t *handle, uint16_t sid); +int service_disconnect(nspire_handle_t *handle); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/devinfo.c b/web/web-libusb/libnspire-sys/libnspire/src/services/devinfo.c new file mode 100644 index 0000000..b4171b6 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/devinfo.c @@ -0,0 +1,117 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include + +#include "handle.h" +#include "error.h" +#include "data.h" +#include "service.h" +#include "endianconv.h" +#include "devinfo.h" + +int nspire_device_info(nspire_handle_t *handle, struct nspire_devinfo *i) { + int ret; + uint8_t buffer[253]; + char *devname, *file, *os; + struct deviceinfo_01 devinfo; + + if ( (ret = service_connect(handle, 0x4020)) ) + return ret; + + if ( (ret = data_write8(handle, 0x01)) ) + goto end; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + /* Shift up one byte to align */ + memmove(&devinfo, buffer+1, sizeof(devinfo)); + + /* Maybe we should convert all this to a data scan call */ + i->storage.free = dcpu64(devinfo.flash_free); + i->storage.total = dcpu64(devinfo.flash_total); + i->ram.free = dcpu64(devinfo.ram_free); + i->ram.total = dcpu64(devinfo.ram_total); + + i->versions[NSPIRE_VER_OS].major = devinfo.p_version[0]; + i->versions[NSPIRE_VER_OS].minor = devinfo.p_version[1]; + i->versions[NSPIRE_VER_OS].build = + devinfo.p_version[2]<<8 | devinfo.p_version[3]; + + i->versions[NSPIRE_VER_BOOT1].major = devinfo.boot1_version[0]; + i->versions[NSPIRE_VER_BOOT1].minor = devinfo.boot1_version[1]; + i->versions[NSPIRE_VER_BOOT1].build = + devinfo.boot1_version[2]<<8 | devinfo.boot1_version[3]; + + i->versions[NSPIRE_VER_BOOT2].major = devinfo.boot2_version[0]; + i->versions[NSPIRE_VER_BOOT2].minor = devinfo.boot2_version[1]; + i->versions[NSPIRE_VER_BOOT2].build = + devinfo.boot2_version[2]<<8 | devinfo.boot2_version[3]; + + i->hw_type = devinfo.device; + + i->batt.status = devinfo.batt_lvl; + i->batt.is_charging = devinfo.is_charging; + i->clock_speed = devinfo.clock_speed; + + i->lcd.width = dcpu16(devinfo.lcd_width); + i->lcd.height = dcpu16(devinfo.lcd_height); + i->lcd.bbp = devinfo.lcd_bbp; + i->lcd.sample_mode = devinfo.lcd_sample_mode; + + memcpy(i->electronic_id, devinfo.full_electronic_id, + sizeof(i->electronic_id) - 1); + i->electronic_id[sizeof(i->electronic_id) - 1] = '\0'; + + i->runlevel = dcpu16(devinfo.run_level); + + if ( (ret = data_write8(handle, 0x02)) ) + goto end; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if ( (ret = data_scan("bS", buffer, sizeof(buffer), + NULL, &devname)) ) + goto end; + + strncpy(i->device_name, devname, sizeof(i->device_name)-1); + i->device_name[sizeof(i->device_name)-1] = '\0'; + + if ( (ret = data_write8(handle, 0x03)) ) + goto end; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if ( (ret = data_scan("bSS", buffer, sizeof(buffer), + NULL, &file, &os)) ) + goto end; + + strncpy(i->extensions.file, file, sizeof(i->extensions.file)-1); + strncpy(i->extensions.os, os, sizeof(i->extensions.os)-1); + + i->extensions.file[sizeof(i->extensions.file)-1] = '\0'; + i->extensions.os[sizeof(i->extensions.os)-1] = '\0'; + + ret = NSPIRE_ERR_SUCCESS; + +end: + service_disconnect(handle); + return ret; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/devinfo.h b/web/web-libusb/libnspire-sys/libnspire/src/services/devinfo.h new file mode 100644 index 0000000..716c1b4 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/devinfo.h @@ -0,0 +1,57 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _DEVINFO_H +#define _DEVINFO_H + +#include "api/devinfo.h" +#ifdef _WIN32 +#define PACK( ... ) __pragma( pack(push, 1) ) __VA_ARGS__ __pragma( pack(pop)) +#else +#define PACK( ... ) __VA_ARGS__ __attribute__((__packed__)) +#endif +PACK(struct deviceinfo_01 { + uint64_t flash_free, flash_total; + uint64_t ram_free, ram_total; + + uint8_t batt_lvl; + + /* Avoid unaligned accesses on some CPUs */ + /* uint16_t is_charging; */ + uint8_t __padding; + uint8_t is_charging; + + uint8_t clock_speed; + + uint8_t p_version[4]; + uint8_t boot1_version[4]; + uint8_t boot2_version[4]; + + uint32_t h_version; + uint16_t run_level; + + uint16_t lcd_x, lcd_y, lcd_width, lcd_height; + uint8_t lcd_bbp; + uint8_t lcd_sample_mode; + + uint8_t device; + + uint8_t electronic_id[17]; + uint8_t full_electronic_id[27]; +}); + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/dir.c b/web/web-libusb/libnspire-sys/libnspire/src/services/dir.c new file mode 100644 index 0000000..6d5d3c4 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/dir.c @@ -0,0 +1,244 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include +#include + +#include "handle.h" +#include "error.h" +#include "data.h" +#include "service.h" +#include "dir.h" + +static int dir_enum(nspire_handle_t *handle, struct nspire_dir_info **d) { + int ret; + char *name; + uint32_t size, date; + uint8_t is_dir; + struct nspire_dir_info *new_dir; + struct nspire_dir_item *current; + + unsigned char buffer[254]; + + if ( (ret = data_write8(handle, 0x0E)) ) + return ret; + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + return ret; + + if (buffer[0] == 0xFF) + return 1; + + if ( (ret = data_scan("hbswwb0", buffer, sizeof(buffer), + NULL, NULL, &name, &size, &date, &is_dir)) ) + return ret; + + new_dir = realloc(*d, sizeof(struct nspire_dir_info) + + (((*d)->num + 1) * sizeof(struct nspire_dir_item))); + if (!new_dir) + return -NSPIRE_ERR_NOMEM; + current = new_dir->items + new_dir->num; + new_dir->num++; + *d = new_dir; + + strncpy(current->name, name, sizeof(current->name)); + current->name[sizeof(current->name)-1] = '\0'; + current->size = size; + current->date = date; + current->type = is_dir; + + return NSPIRE_ERR_SUCCESS; +} + +int nspire_dirlist(nspire_handle_t *handle, const char *path, + struct nspire_dir_info **info_ptr) { + int ret; + size_t len; + uint8_t buffer[254], code; + uint16_t result; + struct nspire_dir_info *d; + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + /* Begin dir enum */ + if ( (ret = data_build("bs0", buffer, sizeof(buffer), &len, + 0x0D, path)) ) + goto end; + + if ( (ret = data_write(handle, buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("bb", buffer, sizeof(buffer), + NULL, &code)) ) + goto end; + + switch (code) { + case 0x0A: + ret = -NSPIRE_ERR_NONEXIST; + goto end; + case 0x0F: + ret = -NSPIRE_ERR_INVALID; + goto end; + } + + d = malloc(sizeof(struct nspire_dir_info)); + (d)->num = 0; + if (!d) { + ret = -NSPIRE_ERR_NOMEM; + goto end; + } + + *info_ptr = d; + /* Start enumerating */ + while (1) { + ret = dir_enum(handle, info_ptr); + if (ret < 0) { + free(*info_ptr); + goto end; + } + + if (ret) + break; + } + + /* End dir enum */ + if ( (ret = data_build("b", buffer, sizeof(buffer), &len, + 0x0F)) ) + goto end; + + if ( (ret = data_write(handle, buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), + NULL, &result)) ) + goto end; + + // TODO: result ignored here, what to do on failure anyway? + + ret = NSPIRE_ERR_SUCCESS; +end: + service_disconnect(handle); + return ret; +} + +void nspire_dirlist_free(struct nspire_dir_info *d) { + free(d); +} + +int nspire_dir_create(nspire_handle_t *handle, const char *path) { + int ret; + size_t len; + uint16_t result; + uint8_t buffer[254]; + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hs", buffer, sizeof(buffer), &len, + 0x0A03, path)) ) + goto end; + + if ( (ret = data_write(handle, &buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, &buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), &result)) ) + goto end; + + ret = (result == 0xFF00) ? NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_EXISTS; +end: + service_disconnect(handle); + return ret; +} + +int nspire_dir_delete(nspire_handle_t *handle, const char *path) { + int ret; + size_t len; + uint16_t result; + uint8_t buffer[254]; + + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hs", buffer, sizeof(buffer), &len, + 0x0B03, path)) ) + goto end; + + if ( (ret = data_write(handle, &buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, &buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), &result)) ) + goto end; + + ret = (result == 0xFF00) ? NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_NONEXIST; +end: + service_disconnect(handle); + return ret; +} + +int nspire_attr(nspire_handle_t *handle, const char *path, + struct nspire_dir_item *info) { + int ret; + size_t len; + uint8_t is_dir, buffer[254]; + uint32_t size, date; + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hs0", buffer, sizeof(buffer), &len, + 0x2001, path)) ) + goto end; + + if ( (ret = data_write(handle, buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if (buffer[0] != 0x20) { + ret = -NSPIRE_ERR_NONEXIST; + goto end; + } + + if ( (ret = data_scan("bwwb0", buffer, sizeof(buffer), + NULL, &size, &date, &is_dir)) ) + goto end; + + strncpy(info->name, path, sizeof(info->name)); + info->name[sizeof(info->name)-1] = '\0'; + info->size = size; + info->date = date; + info->type = is_dir; + + ret = NSPIRE_ERR_SUCCESS; +end: + service_disconnect(handle); + return ret; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/dir.h b/web/web-libusb/libnspire-sys/libnspire/src/services/dir.h new file mode 100644 index 0000000..dec1fd7 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/dir.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _DIR_H +#define _DIR_H + +#include "api/dir.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/file.c b/web/web-libusb/libnspire-sys/libnspire/src/services/file.c new file mode 100644 index 0000000..f22cc47 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/file.c @@ -0,0 +1,234 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include + +#include "handle.h" +#include "error.h" +#include "data.h" +#include "service.h" + +typedef void (*nspire_callback)(size_t, void*); +int nspire_file_write(nspire_handle_t *handle, const char *path, + void* data, size_t size, nspire_callback cb, void *cb_data) { + int ret; + size_t len; + uint8_t buffer[sizeof(struct packet)], *ptr = data; + uint16_t result; + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hsw", buffer, sizeof(buffer), &len, + 0x0301, path, size)) ) + goto end; + + if ( (ret = data_write(handle, buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if (buffer[0] != 0x04) { + ret = -NSPIRE_ERR_INVALID; + goto end; + } + + size_t datasize = packet_max_datasize(handle) - 1; + + buffer[0] = 0x05; + while (size) { + len = (datasize < size) ? datasize : size; + + memcpy(buffer + 1, ptr, len); + if ( (ret = data_write(handle, buffer, len+1)) ) + goto end; + + size -= len; + ptr += len; + + cb(size, cb_data); + } + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), &result)) ) + goto end; + + ret = (result == 0xFF00) ? NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_NONEXIST; +end: + service_disconnect(handle); + return ret; +} + +int nspire_file_read(nspire_handle_t *handle, const char *path, + void* data, size_t size, size_t *total_bytes, nspire_callback cb, void *cb_data) { + int ret; + size_t len; + uint8_t buffer[1440], *ptr = data; + uint16_t result; + uint32_t data_len; + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hs", buffer, packet_max_datasize(handle), &len, + 0x0701, path)) ) + goto end; + + if ( (ret = data_write(handle, buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, buffer, packet_max_datasize(handle), NULL)) ) + goto end; + + if ( (ret = data_scan("h000000000w", buffer, packet_max_datasize(handle), + &result, &data_len)) ) + goto end; + + if (result != 0x0301) { + ret = -NSPIRE_ERR_NONEXIST; + goto end; + } + + if ( (ret = data_write8(handle, 0x04)) ) + goto end; + + if (total_bytes) *total_bytes = 0; + + size_t maxsize = packet_max_datasize(handle) - 1; + + while (data_len) { + len = (maxsize < data_len) ? maxsize : data_len; + + if ( (ret = data_read(handle, buffer, len+1, &len)) ) + goto end; + + size_t to_copy = len - 1; + memcpy(ptr, buffer + 1, (size < to_copy) ? size : to_copy); + if (total_bytes) *total_bytes += (size < to_copy) ? size : to_copy; + size -= (size < to_copy) ? size : to_copy; + if(!size) { + goto end; + } + + ptr += to_copy; + + data_len -= len - 1; + cb(size, cb_data); + } + + if ( (ret = data_write16(handle, 0xFF00)) ) + goto end; + + ret = NSPIRE_ERR_SUCCESS; +end: + service_disconnect(handle); + return ret; +} + +int nspire_file_move(nspire_handle_t *handle, + const char *src, const char *dst) { + int ret; + size_t len; + uint16_t result; + uint8_t buffer[254]; + + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hss0", buffer, sizeof(buffer), &len, + 0x2101, src, dst)) ) + goto end; + + if ( (ret = data_write(handle, &buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, &buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), &result)) ) + goto end; + + ret = (result == 0xFF00) ? NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_INVALID; +end: + service_disconnect(handle); + return ret; +} + +int nspire_file_copy(nspire_handle_t *handle, + const char *src, const char *dst) { + int ret; + size_t len; + uint16_t result; + uint8_t buffer[254]; + + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hss0", buffer, sizeof(buffer), &len, + 0x0C01, src, dst)) ) + goto end; + + if ( (ret = data_write(handle, &buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, &buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), &result)) ) + goto end; + + ret = (result == 0xFF00) ? NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_INVALID; +end: + service_disconnect(handle); + return ret; +} + +int nspire_file_delete(nspire_handle_t *handle, const char *path) { + int ret; + size_t len; + uint16_t result; + uint8_t buffer[254]; + + + if ( (ret = service_connect(handle, 0x4060)) ) + return ret; + + if ( (ret = data_build("hs0", buffer, sizeof(buffer), &len, + 0x0901, path)) ) + goto end; + + if ( (ret = data_write(handle, &buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, &buffer, 2, NULL)) ) + goto end; + + if ( (ret = data_scan("h", buffer, sizeof(buffer), &result)) ) + goto end; + + ret = (result == 0xFF00) ? NSPIRE_ERR_SUCCESS : -NSPIRE_ERR_EXISTS; +end: + service_disconnect(handle); + return ret; +} + + diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/file.h b/web/web-libusb/libnspire-sys/libnspire/src/services/file.h new file mode 100644 index 0000000..66fcd85 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/file.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _FILE_H +#define _FILE_H + +#include "api/file.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/key.c b/web/web-libusb/libnspire-sys/libnspire/src/services/key.c new file mode 100644 index 0000000..c83cc5d --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/key.c @@ -0,0 +1,53 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include +#include + +#include "handle.h" +#include "error.h" +#include "data.h" +#include "service.h" +#include "key.h" + +int nspire_send_key(nspire_handle_t *handle, uint32_t code) { + int ret; + uint8_t buffer[26]; + + if ((ret = service_connect(handle, 0x4042))) + return ret; + + buffer[0] = 1; + buffer[1] = 0; + buffer[2] = 0; + buffer[3] = 0x80; + if ((ret = data_write(handle, buffer, 4))) + goto end; + + memset((void *)buffer, 0, sizeof(buffer)); + buffer[4] = 0x08; + buffer[5] = 0x02; + buffer[6] = (uint8_t)(code >> 16); + buffer[8] = (uint8_t)(code >> 8); + buffer[24] = (uint8_t)(code & 0xFF); + if ((ret = data_write(handle, buffer, sizeof(buffer)))) + goto end; + +end: + service_disconnect(handle); + return ret; +} \ No newline at end of file diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/key.h b/web/web-libusb/libnspire-sys/libnspire/src/services/key.h new file mode 100644 index 0000000..02f5156 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/key.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _KEY_H +#define _KEY_H + +#include "api/key.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/os.c b/web/web-libusb/libnspire-sys/libnspire/src/services/os.c new file mode 100644 index 0000000..b1cabb4 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/os.c @@ -0,0 +1,94 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include + +#include "handle.h" + +#include "error.h" +#include "data.h" +#include "service.h" + +typedef void (*nspire_callback)(size_t, void*); +int nspire_os_send(nspire_handle_t *handle, void* data, size_t size, nspire_callback cb, void *cb_data) { + int ret; + size_t len; + uint8_t buffer[sizeof(struct packet)], *ptr = data; + + if ( (ret = service_connect(handle, 0x4080)) ) + return ret; + + if ( (ret = data_build("bw", buffer, sizeof(buffer), &len, + 0x03, (uint32_t)size)) ) + goto end; + + if ( (ret = data_write(handle, buffer, len)) ) + goto end; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if (buffer[0] != 0x04) { + ret = -NSPIRE_ERR_OSFAILED; + goto end; + } + + size_t datasize = packet_max_datasize(handle) - 1; + buffer[0] = 0x05; + while (size) { + len = (datasize < size) ? datasize : size; + + memcpy(buffer + 1, ptr, len); + if ( (ret = data_write(handle, buffer, len+1)) ) + goto end; + + if (ptr == data) { + /* First run - read 0xFF00 */ + uint16_t code; + if ( (ret = data_read(handle, &code, 2, NULL)) ) + goto end; + + if (dcpu16(code) != 0xFF00 && dcpu16(code) != 0x0400) { + ret = -NSPIRE_ERR_OSFAILED; + goto end; + } + } + + size -= len; + ptr += len; + cb(size, cb_data); + } + + while (1) { + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if (buffer[0] == 0xFF) { + ret = -NSPIRE_ERR_OSFAILED; + goto end; + } + + // Yes, over 100% is actually possible... + if (buffer[1] >= 100) + break; + } + + ret = NSPIRE_ERR_SUCCESS; +end: + service_disconnect(handle); + return ret; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/os.h b/web/web-libusb/libnspire-sys/libnspire/src/services/os.h new file mode 100644 index 0000000..587685c --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/os.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _OS_H +#define _OS_H + +#include "api/os.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/screenshot.c b/web/web-libusb/libnspire-sys/libnspire/src/services/screenshot.c new file mode 100644 index 0000000..65938e6 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/screenshot.c @@ -0,0 +1,123 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include +#include + +#include "handle.h" +#include "error.h" +#include "data.h" +#include "service.h" +#include "screenshot.h" + +struct rle { + signed char len; + unsigned char byte; +}; + +static void rle_decode(const void *in, void *_out, + size_t in_size, size_t out_size) { + size_t len; + unsigned char *out = _out; + const struct rle *ptr = in; + + while (in_size > 1 && out_size) { + if (ptr->len < 0) { + len = -(ptr->len) + 1; + len = len < out_size ? len : out_size; + len = len < in_size ? len : in_size; + + memcpy(out, &ptr->byte, len); + + in_size -= (1 + (len)); + ptr = (void*)((unsigned char*)ptr + (1 + (len))); + } else { + len = ptr->len + 1; + len = len < out_size ? len : out_size; + memset(out, ptr->byte, len); + + in_size -= sizeof(struct rle); + ptr++; + } + + out_size -= len; + out += len; + } +} + +int nspire_screenshot(nspire_handle_t *handle, struct nspire_image **ptr) { + int ret; + size_t len, in_len, out_len; + uint8_t buffer[254], bbp, *tmp = NULL, *tmp_ptr = NULL; + uint16_t width, height; + uint32_t size; + struct nspire_image *i; + + + if ( (ret = service_connect(handle, 0x4024)) ) + return ret; + + if ( (ret = data_write8(handle, 0x00)) ) + return ret; + + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto end; + + if ( (ret = data_scan("bwhhhhbb", buffer, sizeof(buffer), + NULL, &size, NULL, NULL, &width, &height, &bbp, NULL)) ) + goto end; + + tmp_ptr = tmp = malloc(size); + if (!tmp) { + ret = -NSPIRE_ERR_NOMEM; + goto end; + } + + in_len = size; + out_len = (width * height * bbp) / 8; + + i = malloc(sizeof(*i) + out_len); + if (!i) { + ret = -NSPIRE_ERR_NOMEM; + goto end; + } + + i->width = width; + i->height = height; + i->bbp = bbp; + + while (size) { + if ( (ret = data_read(handle, buffer, sizeof(buffer), NULL)) ) + goto error_free; + + len = 253 < size ? 253 : size; + memcpy(tmp_ptr, buffer + 1, len); + tmp_ptr += len; + size -= len; + } + + rle_decode(tmp, i->data, in_len, out_len); + *ptr = i; + ret = NSPIRE_ERR_SUCCESS; + goto end; +error_free: + if (i) free(i); +end: + if (tmp) free(tmp); + service_disconnect(handle); + return ret; +} diff --git a/web/web-libusb/libnspire-sys/libnspire/src/services/screenshot.h b/web/web-libusb/libnspire-sys/libnspire/src/services/screenshot.h new file mode 100644 index 0000000..3dcc145 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/services/screenshot.h @@ -0,0 +1,23 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _SCREENSHOT_H +#define _SCREENSHOT_H + +#include "api/screenshot.h" + +#endif diff --git a/web/web-libusb/libnspire-sys/libnspire/src/usb.c b/web/web-libusb/libnspire-sys/libnspire/src/usb.c new file mode 100644 index 0000000..37fd7dd --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/usb.c @@ -0,0 +1,120 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#include "usb.h" +#include "error.h" + +#include + +#define NSP_DEFAULT_CONFIG 1 +#define NSP_DEFAULT_IFACE 0 +#define NSP_TIMEOUT 10000 + +static libusb_context * usb_ctx = NULL; + +int usb_init() { + if (usb_ctx) + return NSPIRE_ERR_SUCCESS; + + if (libusb_init(&usb_ctx)) + return -NSPIRE_ERR_LIBUSB; + + //libusb_set_debug(usb_ctx, 3); + + return NSPIRE_ERR_SUCCESS; +} + +void usb_finish() { + libusb_exit(usb_ctx); +} + +int usb_get_device(usb_device_t *handle, libusb_device_handle *dev) { + int i; + struct libusb_config_descriptor *config; + const struct libusb_interface_descriptor *iface; + + /* Libusb boilerplate */ + if (libusb_set_configuration(dev, NSP_DEFAULT_CONFIG)) + goto error_close; + if (libusb_reset_device(dev)) + goto error_close; + if (libusb_claim_interface(dev, NSP_DEFAULT_IFACE)) + goto error_close; + + /* Find and use first found input and output endpoints */ + /* We can't hardcode or else it won't work in recovery mode */ + if (libusb_get_active_config_descriptor( + libusb_get_device(dev), &config)) + goto error_close; + if (config->bNumInterfaces < NSP_DEFAULT_IFACE) + goto error_free_desc; + iface = config->interface[NSP_DEFAULT_IFACE].altsetting; + + handle->ep_in = 0; + handle->ep_out = 0; + for (i=0; ibNumEndpoints; i++) { + unsigned char ep = iface->endpoint[i].bEndpointAddress; + if (ep & LIBUSB_ENDPOINT_IN) { + if (!handle->ep_in) handle->ep_in = ep; + } else { + if (!handle->ep_out) handle->ep_out = ep; + } + } + libusb_free_config_descriptor(config); + + if (!handle->ep_in || !handle->ep_out) + goto error_close; + + handle->dev = dev; + return NSPIRE_ERR_SUCCESS; +error_free_desc: + libusb_free_config_descriptor(config); +error_close: +error: + return -NSPIRE_ERR_NODEVICE; +} + +void usb_free_device(usb_device_t *handle) { + libusb_release_interface(handle->dev, NSP_DEFAULT_IFACE); +} + +static inline int usb_xfer(libusb_device_handle *handle, unsigned char ep, + void *ptr, int len) { + int ret, transferred = 0; + ret = libusb_bulk_transfer(handle, + ep, + ptr, + len, + &transferred, + NSP_TIMEOUT); + + switch (ret) { + case 0: return (len - transferred); + case LIBUSB_ERROR_NO_DEVICE: return -NSPIRE_ERR_NODEVICE; + case LIBUSB_ERROR_TIMEOUT: return -NSPIRE_ERR_TIMEOUT; + default: return -NSPIRE_ERR_LIBUSB; + } +} + +int usb_write(usb_device_t *handle, void *ptr, int len) { + return usb_xfer(handle->dev, handle->ep_out, ptr, len); +} + +int usb_read(usb_device_t *handle, void *ptr, int len) { + return usb_xfer(handle->dev, handle->ep_in, ptr, len); +} + diff --git a/web/web-libusb/libnspire-sys/libnspire/src/usb.h b/web/web-libusb/libnspire-sys/libnspire/src/usb.h new file mode 100644 index 0000000..1a849e8 --- /dev/null +++ b/web/web-libusb/libnspire-sys/libnspire/src/usb.h @@ -0,0 +1,40 @@ +/* + This file is part of libnspire. + + libnspire is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libnspire is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libnspire. If not, see . +*/ + +#ifndef _USB_H +#define _USB_H + +#include "endianconv.h" +#include + +#define NSP_VID 0x0451 +#define NSP_PID 0xe012 +#define NSP_PID_CX2 0xe022 + +typedef struct { + libusb_device_handle *dev; + unsigned char ep_in, ep_out; +} usb_device_t; + +int usb_init(); +void usb_finish(); +int usb_get_device(usb_device_t *handle, libusb_device_handle *dev); +void usb_free_device(usb_device_t *handle); +int usb_write(usb_device_t *handle, void *ptr, int len); +int usb_read(usb_device_t *handle, void *ptr, int len); + +#endif diff --git a/web/web-libusb/libnspire-sys/src/bindings.rs b/web/web-libusb/libnspire-sys/src/bindings.rs new file mode 100644 index 0000000..9267ef2 --- /dev/null +++ b/web/web-libusb/libnspire-sys/src/bindings.rs @@ -0,0 +1,995 @@ +/* automatically generated by rust-bindgen 0.55.1 */ + +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +pub type __uint8_t = ::std::os::raw::c_uchar; +pub type __uint16_t = ::std::os::raw::c_ushort; +pub type __uint32_t = ::std::os::raw::c_uint; +pub type __uint64_t = ::std::os::raw::c_ulong; +extern "C" { + pub fn free(__ptr: *mut ::std::os::raw::c_void); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_handle { + _unused: [u8; 0], +} +pub type nspire_handle_t = nspire_handle; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct libusb_device_handle { + _unused: [u8; 0], +} +extern "C" { + pub fn nspire_init( + ptr: *mut *mut nspire_handle_t, + dev: *mut libusb_device_handle, + is_cx2: bool, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_free(ptr: *mut nspire_handle_t); +} +pub const nspire_battery_NSPIRE_BATT_POWERED: nspire_battery = 0; +pub const nspire_battery_NSPIRE_BATT_LOW: nspire_battery = 241; +pub const nspire_battery_NSPIRE_BATT_OK: nspire_battery = 127; +pub const nspire_battery_NSPIRE_BATT_UNKNOWN: nspire_battery = 255; +pub type nspire_battery = ::std::os::raw::c_uint; +pub const nspire_version_index_NSPIRE_VER_OS: nspire_version_index = 0; +pub const nspire_version_index_NSPIRE_VER_BOOT1: nspire_version_index = 1; +pub const nspire_version_index_NSPIRE_VER_BOOT2: nspire_version_index = 2; +pub const nspire_version_index_NSPIRE_VER_MAXNUM: nspire_version_index = 3; +pub type nspire_version_index = ::std::os::raw::c_uint; +pub const nspire_type_NSPIRE_CAS: nspire_type = 14; +pub const nspire_type_NSPIRE_NONCAS: nspire_type = 30; +pub const nspire_type_NSPIRE_CASCX: nspire_type = 15; +pub const nspire_type_NSPIRE_NONCASCX: nspire_type = 31; +pub type nspire_type = ::std::os::raw::c_uint; +pub const nspire_runlevel_NSPIRE_RUNLEVEL_RECOVERY: nspire_runlevel = 1; +pub const nspire_runlevel_NSPIRE_RUNLEVEL_OS: nspire_runlevel = 2; +pub type nspire_runlevel = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo { + pub storage: nspire_devinfo__bindgen_ty_1, + pub ram: nspire_devinfo__bindgen_ty_2, + pub versions: [nspire_devinfo__bindgen_ty_3; 3usize], + pub hw_type: nspire_type, + pub batt: nspire_devinfo__bindgen_ty_4, + pub clock_speed: u8, + pub lcd: nspire_devinfo__bindgen_ty_5, + pub extensions: nspire_devinfo__bindgen_ty_6, + pub device_name: [::std::os::raw::c_char; 20usize], + pub electronic_id: [::std::os::raw::c_char; 28usize], + pub runlevel: nspire_runlevel, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo__bindgen_ty_1 { + pub free: u64, + pub total: u64, +} +#[test] +fn bindgen_test_layout_nspire_devinfo__bindgen_ty_1() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(nspire_devinfo__bindgen_ty_1)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(nspire_devinfo__bindgen_ty_1)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).free as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_1), + "::", + stringify!(free) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).total as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_1), + "::", + stringify!(total) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo__bindgen_ty_2 { + pub free: u64, + pub total: u64, +} +#[test] +fn bindgen_test_layout_nspire_devinfo__bindgen_ty_2() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(nspire_devinfo__bindgen_ty_2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(nspire_devinfo__bindgen_ty_2)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).free as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_2), + "::", + stringify!(free) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).total as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_2), + "::", + stringify!(total) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo__bindgen_ty_3 { + pub major: u8, + pub minor: u8, + pub build: u16, +} +#[test] +fn bindgen_test_layout_nspire_devinfo__bindgen_ty_3() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(nspire_devinfo__bindgen_ty_3)) + ); + assert_eq!( + ::std::mem::align_of::(), + 2usize, + concat!("Alignment of ", stringify!(nspire_devinfo__bindgen_ty_3)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).major as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_3), + "::", + stringify!(major) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).minor as *const _ as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_3), + "::", + stringify!(minor) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).build as *const _ as usize + }, + 2usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_3), + "::", + stringify!(build) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo__bindgen_ty_4 { + pub status: nspire_battery, + pub is_charging: u8, +} +#[test] +fn bindgen_test_layout_nspire_devinfo__bindgen_ty_4() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(nspire_devinfo__bindgen_ty_4)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(nspire_devinfo__bindgen_ty_4)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).status as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_4), + "::", + stringify!(status) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).is_charging as *const _ + as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_4), + "::", + stringify!(is_charging) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo__bindgen_ty_5 { + pub width: u16, + pub height: u16, + pub bbp: u8, + pub sample_mode: u8, +} +#[test] +fn bindgen_test_layout_nspire_devinfo__bindgen_ty_5() { + assert_eq!( + ::std::mem::size_of::(), + 6usize, + concat!("Size of: ", stringify!(nspire_devinfo__bindgen_ty_5)) + ); + assert_eq!( + ::std::mem::align_of::(), + 2usize, + concat!("Alignment of ", stringify!(nspire_devinfo__bindgen_ty_5)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).width as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_5), + "::", + stringify!(width) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).height as *const _ as usize + }, + 2usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_5), + "::", + stringify!(height) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).bbp as *const _ as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_5), + "::", + stringify!(bbp) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).sample_mode as *const _ + as usize + }, + 5usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_5), + "::", + stringify!(sample_mode) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nspire_devinfo__bindgen_ty_6 { + pub file: [::std::os::raw::c_char; 8usize], + pub os: [::std::os::raw::c_char; 8usize], +} +#[test] +fn bindgen_test_layout_nspire_devinfo__bindgen_ty_6() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(nspire_devinfo__bindgen_ty_6)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(nspire_devinfo__bindgen_ty_6)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).file as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_6), + "::", + stringify!(file) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).os as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo__bindgen_ty_6), + "::", + stringify!(os) + ) + ); +} +#[test] +fn bindgen_test_layout_nspire_devinfo() { + assert_eq!( + ::std::mem::size_of::(), + 136usize, + concat!("Size of: ", stringify!(nspire_devinfo)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(nspire_devinfo)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).storage as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(storage) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).ram as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(ram) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).versions as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(versions) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).hw_type as *const _ as usize }, + 44usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(hw_type) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).batt as *const _ as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(batt) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).clock_speed as *const _ as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(clock_speed) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).lcd as *const _ as usize }, + 58usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(lcd) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).extensions as *const _ as usize }, + 64usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(extensions) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).device_name as *const _ as usize }, + 80usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(device_name) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).electronic_id as *const _ as usize }, + 100usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(electronic_id) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).runlevel as *const _ as usize }, + 128usize, + concat!( + "Offset of field: ", + stringify!(nspire_devinfo), + "::", + stringify!(runlevel) + ) + ); +} +extern "C" { + pub fn nspire_device_info( + handle: *mut nspire_handle_t, + i: *mut nspire_devinfo, + ) -> ::std::os::raw::c_int; +} +impl nspire_keys { + pub const KEYNSP_CTRL_A: nspire_keys = nspire_keys::KEYNSP_A; +} +impl nspire_keys { + pub const KEYNSP_CTRL_PI: nspire_keys = nspire_keys::KEYNSP_SHIFT_DOWN; +} +impl nspire_keys { + pub const KEYNSP_SHIFT_BACK_SPACE: nspire_keys = nspire_keys::KEYNSP_BACK_SPACE; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum nspire_keys { + KEYNSP_ESC = 1807872, + KEYNSP_CTRL_ESC = 61184, + KEYNSP_TAB = 627968, + KEYNSP_SHIFT_TAB = 8164608, + KEYNSP_CTRL_TAB = 60672, + KEYNSP_HOME = 64768, + KEYNSP_CTRL_HOME = 65024, + KEYNSP_MENU = 13824, + KEYNSP_CTRL_MENU = 52736, + KEYNSP_MOUSE_CONTEXT_MENU = 40960, + KEYNSP_CLICK = 44288, + KEYNSP_CTRL_CLICK = 44032, + KEYNSP_SHIFT_GRAB = 63744, + KEYNSP_LEFT = 1792, + KEYNSP_SHIFT_LEFT = 61696, + KEYNSP_SHIFT_HOLD_LEFT = 1795, + KEYNSP_CTRL_LEFT = 55808, + KEYNSP_RIGHT = 9984, + KEYNSP_SHIFT_RIGHT = 61952, + KEYNSP_SHIFT_HOLD_RIGHT = 9987, + KEYNSP_CTRL_RIGHT = 56064, + KEYNSP_UP = 5888, + KEYNSP_SHIFT_UP = 62208, + KEYNSP_SHIFT_HOLD_UP = 5891, + KEYNSP_CTRL_UP = 56320, + KEYNSP_DOWN = 14080, + KEYNSP_SHIFT_DOWN = 62464, + KEYNSP_SHIFT_HOLD_DOWN = 14083, + KEYNSP_CTRL_DOWN = 56576, + KEYNSP_EQUAL = 4027648, + KEYNSP_CTRL_EQUAL = 59648, + KEYNSP_SUCH_THAT = 8187136, + KEYNSP_A = 6383104, + KEYNSP_SHIFT_A = 4285952, + KEYNSP_B = 6440448, + KEYNSP_SHIFT_B = 4343296, + KEYNSP_CTRL_B = 176384, + KEYNSP_C = 6497792, + KEYNSP_SHIFT_C = 4400640, + KEYNSP_CTRL_C = 242176, + KEYNSP_FLAG = 42752, + KEYNSP_CTRL_FLAG = 63488, + KEYNSP_LESS_THAN = 3974656, + KEYNSP_CTRL_LESS_THAN = 52992, + KEYNSP_D = 6587648, + KEYNSP_SHIFT_D = 4490496, + KEYNSP_CTRL_D = 307968, + KEYNSP_E = 6644992, + KEYNSP_SHIFT_E = 4547840, + KEYNSP_CTRL_E = 373760, + KEYNSP_F = 6702336, + KEYNSP_SHIFT_F = 4605184, + KEYNSP_CTRL_F = 439552, + KEYNSP_G = 6759680, + KEYNSP_SHIFT_G = 4662528, + KEYNSP_CTRL_G = 505344, + KEYNSP_TILDE = 2618624, + KEYNSP_CTRL_TILDE = 2360576, + KEYNSP_GREATER_THAN = 4097536, + KEYNSP_CTRL_GREATER_THAN = 56832, + KEYNSP_H = 6849536, + KEYNSP_SHIFT_H = 4752384, + KEYNSP_CTRL_H = 571136, + KEYNSP_I = 6906880, + KEYNSP_SHIFT_I = 4809728, + KEYNSP_CTRL_I = 636928, + KEYNSP_J = 6964224, + KEYNSP_SHIFT_J = 4867072, + KEYNSP_CTRL_J = 702720, + KEYNSP_K = 7021568, + KEYNSP_SHIFT_K = 4924416, + KEYNSP_CTRL_K = 768512, + KEYNSP_QUOTE = 2269440, + KEYNSP_IMAGINARY = 41472, + KEYNSP_CTRL_IMAGINARY = 41216, + KEYNSP_L = 7111424, + KEYNSP_SHIFT_L = 5014272, + KEYNSP_CTRL_L = 834304, + KEYNSP_M = 7168768, + KEYNSP_SHIFT_M = 5071616, + KEYNSP_CTRL_M = 900096, + KEYNSP_N = 7226112, + KEYNSP_SHIFT_N = 5128960, + KEYNSP_CTRL_N = 965888, + KEYNSP_O = 7283456, + KEYNSP_SHIFT_O = 5186304, + KEYNSP_CTRL_O = 1031680, + KEYNSP_COLON = 3801344, + KEYNSP_CTRL_COLON = 3867136, + KEYNSP_EXP = 41984, + KEYNSP_P = 7373312, + KEYNSP_SHIFT_P = 5276160, + KEYNSP_CTRL_P = 1097472, + KEYNSP_Q = 7430656, + KEYNSP_SHIFT_Q = 5333504, + KEYNSP_CTRL_Q = 1163264, + KEYNSP_R = 7488000, + KEYNSP_SHIFT_R = 5390848, + KEYNSP_CTRL_R = 1229056, + KEYNSP_S = 7545344, + KEYNSP_SHIFT_S = 5448192, + KEYNSP_CTRL_S = 1294848, + KEYNSP_QUESTION_MARK = 4129536, + KEYNSP_CTRL_QUESTION_MARK = 51968, + KEYNSP_PI = 41728, + KEYNSP_T = 7635200, + KEYNSP_SHIFT_T = 5538048, + KEYNSP_CTRL_T = 1360640, + KEYNSP_U = 7692544, + KEYNSP_SHIFT_U = 5595392, + KEYNSP_CTRL_U = 1426432, + KEYNSP_V = 7749888, + KEYNSP_SHIFT_V = 5652736, + KEYNSP_CTRL_V = 1492224, + KEYNSP_W = 7807232, + KEYNSP_SHIFT_W = 5710080, + KEYNSP_CTRL_W = 1558016, + KEYNSP_COMMA = 2924544, + KEYNSP_THETA = 8914432, + KEYNSP_X = 7897088, + KEYNSP_SHIFT_X = 5799936, + KEYNSP_CTRL_X = 1623808, + KEYNSP_Y = 7954432, + KEYNSP_SHIFT_Y = 5857280, + KEYNSP_CTRL_Y = 1689600, + KEYNSP_Z = 8011776, + KEYNSP_SHIFT_Z = 5914624, + KEYNSP_CTRL_Z = 1755392, + KEYNSP_SPACE = 2105344, + KEYNSP_CTRL_SPACE = 52480, + KEYNSP_NEW_LINE = 2560, + KEYNSP_CTRL = 43524, + KEYNSP_SHIFT = 43779, + KEYNSP_CTRL_SHIFT = 43783, + KEYNSP_BACK_SPACE = 529664, + KEYNSP_CTRL_BACK_SPACE = 58116, + KEYNSP_VAR = 44800, + KEYNSP_CTRL_VAR = 43008, + KEYNSP_LEFT_PARENTHESES = 2643200, + KEYNSP_CTRL_LEFT_PARENTHESES = 59136, + KEYNSP_RIGHT_PARENTHESES = 2700544, + KEYNSP_CTRL_RIGHT_PARENTHESES = 58624, + KEYNSP_CATALOG = 37120, + KEYNSP_CTRL_CATALOG = 60928, + KEYNSP_POWER = 6198016, + KEYNSP_CTRL_POWER = 60160, + KEYNSP_SIN = 29696, + KEYNSP_CTRL_SIN = 59392, + KEYNSP_COS = 21504, + KEYNSP_CTRL_COS = 58880, + KEYNSP_TAN = 13312, + KEYNSP_CTRL_TAN = 58368, + KEYNSP_SLASH = 3085312, + KEYNSP_CTRL_SLASH = 57856, + KEYNSP_SQUARE = 37632, + KEYNSP_CTRL_SQUARE = 37376, + KEYNSP_SEVEN = 3633408, + KEYNSP_CTRL_SEVEN = 55040, + KEYNSP_EIGHT = 3690752, + KEYNSP_CTRL_EIGHT = 55296, + KEYNSP_NINE = 3748096, + KEYNSP_CTRL_NINE = 55552, + KEYNSP_TIMES = 2757376, + KEYNSP_CTRL_TIMES = 57600, + KEYNSP_TEN_POWER = 60416, + KEYNSP_CTRL_TEN_POWER = 37888, + KEYNSP_FOUR = 3437056, + KEYNSP_CTRL_FOUR = 54272, + KEYNSP_FIVE = 3494400, + KEYNSP_CTRL_FIVE = 54528, + KEYNSP_SIX = 3551744, + KEYNSP_CTRL_SIX = 54784, + KEYNSP_MINUS = 2953728, + KEYNSP_CTRL_MINUS = 57344, + KEYNSP_E_POWER = 51712, + KEYNSP_CTRL_E_POWER = 43264, + KEYNSP_ONE = 3240704, + KEYNSP_CTRL_ONE = 53504, + KEYNSP_TWO = 3298048, + KEYNSP_CTRL_TWO = 53760, + KEYNSP_THREE = 3355392, + KEYNSP_CTRL_THREE = 54016, + KEYNSP_PLUS = 2822400, + KEYNSP_CTRL_PLUS = 57088, + KEYNSP_ON = 2816, + KEYNSP_CTRL_ON = 61440, + KEYNSP_ZERO = 3166208, + KEYNSP_CTRL_ZERO = 53248, + KEYNSP_POINT = 3043328, + KEYNSP_NEG = 11612160, + KEYNSP_CTRL_NEG = 44544, + KEYNSP_ENTER = 856064, + KEYNSP_CTRL_ENTER = 42496, +} +extern "C" { + pub fn nspire_send_key(handle: *mut nspire_handle_t, code: u32) -> ::std::os::raw::c_int; +} +pub type nspire_callback = + ::std::option::Option; +extern "C" { + pub fn nspire_file_write( + arg1: *mut nspire_handle_t, + arg2: *const ::std::os::raw::c_char, + arg3: *mut ::std::os::raw::c_void, + arg4: usize, + cb: nspire_callback, + cb_data: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_file_read( + handle: *mut nspire_handle_t, + path: *const ::std::os::raw::c_char, + data: *mut ::std::os::raw::c_void, + size: usize, + read_bytes: *mut usize, + cb: nspire_callback, + cb_data: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_file_move( + handle: *mut nspire_handle_t, + src: *const ::std::os::raw::c_char, + dst: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_file_copy( + handle: *mut nspire_handle_t, + src: *const ::std::os::raw::c_char, + dst: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_file_delete( + handle: *mut nspire_handle_t, + path: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +pub const nspire_dir_type_NSPIRE_FILE: nspire_dir_type = 0; +pub const nspire_dir_type_NSPIRE_DIR: nspire_dir_type = 1; +pub type nspire_dir_type = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct nspire_dir_item { + pub name: [::std::os::raw::c_char; 240usize], + pub size: u64, + pub date: u64, + pub type_: nspire_dir_type, +} +#[test] +fn bindgen_test_layout_nspire_dir_item() { + assert_eq!( + ::std::mem::size_of::(), + 264usize, + concat!("Size of: ", stringify!(nspire_dir_item)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(nspire_dir_item)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_dir_item), + "::", + stringify!(name) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).size as *const _ as usize }, + 240usize, + concat!( + "Offset of field: ", + stringify!(nspire_dir_item), + "::", + stringify!(size) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).date as *const _ as usize }, + 248usize, + concat!( + "Offset of field: ", + stringify!(nspire_dir_item), + "::", + stringify!(date) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, + 256usize, + concat!( + "Offset of field: ", + stringify!(nspire_dir_item), + "::", + stringify!(type_) + ) + ); +} +#[repr(C)] +pub struct nspire_dir_info { + pub num: u64, + pub items: __IncompleteArrayField, +} +#[test] +fn bindgen_test_layout_nspire_dir_info() { + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(nspire_dir_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(nspire_dir_info)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).num as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_dir_info), + "::", + stringify!(num) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).items as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(nspire_dir_info), + "::", + stringify!(items) + ) + ); +} +extern "C" { + pub fn nspire_dirlist( + arg1: *mut nspire_handle_t, + arg2: *const ::std::os::raw::c_char, + arg3: *mut *mut nspire_dir_info, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_dirlist_free(d: *mut nspire_dir_info); +} +extern "C" { + pub fn nspire_dir_create( + handle: *mut nspire_handle_t, + path: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_dir_delete( + handle: *mut nspire_handle_t, + path: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn nspire_attr( + arg1: *mut nspire_handle_t, + arg2: *const ::std::os::raw::c_char, + arg3: *mut nspire_dir_item, + ) -> ::std::os::raw::c_int; +} +pub const NSPIRE_ERR_SUCCESS: ::std::os::raw::c_uint = 0; +pub const NSPIRE_ERR_TIMEOUT: ::std::os::raw::c_uint = 1; +pub const NSPIRE_ERR_NOMEM: ::std::os::raw::c_uint = 2; +pub const NSPIRE_ERR_INVALID: ::std::os::raw::c_uint = 3; +pub const NSPIRE_ERR_LIBUSB: ::std::os::raw::c_uint = 4; +pub const NSPIRE_ERR_NODEVICE: ::std::os::raw::c_uint = 5; +pub const NSPIRE_ERR_INVALPKT: ::std::os::raw::c_uint = 6; +pub const NSPIRE_ERR_NACK: ::std::os::raw::c_uint = 7; +pub const NSPIRE_ERR_BUSY: ::std::os::raw::c_uint = 8; +pub const NSPIRE_ERR_EXISTS: ::std::os::raw::c_uint = 9; +pub const NSPIRE_ERR_NONEXIST: ::std::os::raw::c_uint = 10; +pub const NSPIRE_ERR_OSFAILED: ::std::os::raw::c_uint = 11; +pub const NSPIRE_ERR_MAX: ::std::os::raw::c_uint = 12; +pub type _bindgen_ty_5 = ::std::os::raw::c_uint; +extern "C" { + pub fn nspire_strerror(error: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn nspire_os_send( + handle: *mut nspire_handle_t, + data: *mut ::std::os::raw::c_void, + size: usize, + cb: nspire_callback, + cb_data: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; +} +#[repr(C)] +#[derive(Debug)] +pub struct nspire_image { + pub width: u16, + pub height: u16, + pub bbp: u8, + pub data: __IncompleteArrayField<::std::os::raw::c_uchar>, +} +#[test] +fn bindgen_test_layout_nspire_image() { + assert_eq!( + ::std::mem::size_of::(), + 6usize, + concat!("Size of: ", stringify!(nspire_image)) + ); + assert_eq!( + ::std::mem::align_of::(), + 2usize, + concat!("Alignment of ", stringify!(nspire_image)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).width as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nspire_image), + "::", + stringify!(width) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).height as *const _ as usize }, + 2usize, + concat!( + "Offset of field: ", + stringify!(nspire_image), + "::", + stringify!(height) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).bbp as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(nspire_image), + "::", + stringify!(bbp) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, + 5usize, + concat!( + "Offset of field: ", + stringify!(nspire_image), + "::", + stringify!(data) + ) + ); +} +extern "C" { + pub fn nspire_screenshot( + handle: *mut nspire_handle_t, + ptr: *mut *mut nspire_image, + ) -> ::std::os::raw::c_int; +} diff --git a/web/web-libusb/libnspire-sys/src/lib.rs b/web/web-libusb/libnspire-sys/src/lib.rs new file mode 100644 index 0000000..5acbf08 --- /dev/null +++ b/web/web-libusb/libnspire-sys/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +extern crate libusb1_sys; +include!("bindings.rs"); diff --git a/web/web-libusb/web-libnspire/Cargo.toml b/web/web-libusb/web-libnspire/Cargo.toml index b32025a..e64f12f 100644 --- a/web/web-libusb/web-libnspire/Cargo.toml +++ b/web/web-libusb/web-libnspire/Cargo.toml @@ -31,3 +31,10 @@ console_error_panic_hook = { version = "0.1.6", optional = true } [dev-dependencies] wasm-bindgen-test = "0.3.13" +[package.metadata.wasm-pack.profile.dev.wasm-bindgen] +# Should wasm-bindgen demangle the symbols in the "name" custom section? +demangle-name-section = true +# Should we emit the DWARF debug info custom sections? +dwarf-debug-info = true +[package.metadata.wasm-pack.profile.dev] +wasm-opt = ['-g'] diff --git a/web/web-libusb/web-libnspire/pkg/web_libnspire_bg.wasm b/web/web-libusb/web-libnspire/pkg/web_libnspire_bg.wasm index a11a417..23d735f 100644 Binary files a/web/web-libusb/web-libnspire/pkg/web_libnspire_bg.wasm and b/web/web-libusb/web-libnspire/pkg/web_libnspire_bg.wasm differ diff --git a/web/web-libusb/web-libnspire/src/printf.rs b/web/web-libusb/web-libnspire/src/printf.rs index 5c0e2ab..3b8783e 100644 --- a/web/web-libusb/web-libnspire/src/printf.rs +++ b/web/web-libusb/web-libnspire/src/printf.rs @@ -34,6 +34,7 @@ pub fn to_write<'a>(w: &'a mut impl fmt::Write) -> impl FnMut(Argument) + 'a { move |arg| match arg { Argument::Extra(d) => {w.write_str(&String::from_utf8_lossy(d));}, Argument::Hex(len, data) => {write!(w, "{:#0width$x}", data, width=len as usize);}, + Argument::Int(data) => {write!(w, "{}", data);}, e => {dbg!(e);}, } } diff --git a/web/web-libusb/web-libusb/src/lib.rs b/web/web-libusb/web-libusb/src/lib.rs index d2514f8..8a5c1f0 100644 --- a/web/web-libusb/web-libusb/src/lib.rs +++ b/web/web-libusb/web-libusb/src/lib.rs @@ -179,7 +179,9 @@ pub unsafe extern "C" fn libusb_bulk_transfer( }) { Ok(reply) => match reply.0 { Ok(size) => { - *transferred = size as c_int; + if !transferred.is_null() { + *transferred = size as c_int; + } LIBUSB_SUCCESS } Err(e) => e.into(), @@ -202,6 +204,9 @@ pub unsafe extern "C" fn libusb_bulk_transfer( Ok(buf) => { slice::from_raw_parts_mut(data, (buf.0).len().min(length as usize)) .copy_from_slice(buf.0); + if !transferred.is_null() { + *transferred = (buf.0).len() as c_int; + } LIBUSB_SUCCESS } Err(e) => e.into(),