Git Product home page Git Product logo

hid's Introduction

AppVeyor GoDoc

Gopher Interface Devices (USB HID)

The hid package is a cross platform library for accessing and communicating with USB Human Interface Devices (HID). It is an alternative package to gousb for use cases where devices support this ligher mode of operation (e.g. input devices, hardware crypto wallets).

The package wraps hidapi for accessing OS specific USB HID APIs directly instead of using low level USB constructs, which might have permission issues on some platforms. The hidapi dependency is vendored directly into the repository and wrapped using CGO, making the hid package self-contained and go-gettable.

Supported platforms at the moment are Linux, macOS and Windows (exclude constraints are also specified for Android and iOS to allow smoother vendoring into cross platform projects).

The hidapi on linux unfortunately requires libuddev (libudev-dev on ubuntu, systemd-devel on fedora). Therefore, this library includes libusb which we use as a backend on linux, and thus avoid runtime dependencies.

Cross-compiling

Using go get the embedded C library is compiled into the binary format of your host OS. Cross compiling to a different platform or architecture entails disabling CGO by default in Go, causing device enumeration hid.Enumerate() to yield no results.

To cross compile a functional version of this library, you'll need to enable CGO during cross compilation via CGO_ENABLED=1 and you'll need to install and set a cross compilation enabled C toolkit via CC=your-cross-gcc.

Acknowledgements

Although the hid package is an implementation from scratch, it was heavily inspired by the existing go.hid library, which seems abandoned since 2015; is incompatible with Go 1.6+; and has various external dependencies. Given its inspirational roots, I thought it important to give credit to the author of said package too.

Wide character support in the hid package is done via the gowchar library, unmaintained since 2013; non buildable with a modern Go release and failing go vet checks. As such, gowchar was also vendored in inline (copyright headers and origins preserved).

License

The components of hid are licensed as such:

Given the above, hid is licensed under GNU LGPL 2.1 or later on Linux and 3-clause BSD on other platforms.

hid's People

Contributors

aaazalea avatar bpedman avatar dolmen avatar fjl avatar gballet avatar holiman avatar karalabe avatar neheb avatar neverpanic avatar toudi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hid's Issues

Compatible with gomobile?

Hi

Thank you for this amazing package.

Would you know if this library can be used together with gomobile bind to access usb devices on android/ios?

I am trying it, it compiles fine, but I get zero results from the Enumerate(0,0) call.

Thanks.

Usage with go-streamdeck under windows - a fix I do not understand

Hi,

I am trying to use go-streamdeck, which internal uses karalabe/hid.

Its a library to control the elgato Stream Deck.

It works under linux, but fails under windows with:

panic: hidapi: Falscher Parameter.

Which is german for "wrong Parameter".

Without known much about USB, and HID: At one point tried the following:

I removed the windows specificas in these lines:

        if runtime.GOOS == "windows" {
		report = append([]byte{0x00}, b...)
	} else {
		report = b
	}

with

    report = b

At these lines: https://github.com/karalabe/hid/blob/master/hid_enabled.go#L167

Now it works!

I have no Idea why.

Should this be fixed? Or is my device strange?
What would be a good way to write a patch so I can used the unmodifed HID library?

Poll.h not found

# github.com/zondax/hid
../../../../pkg/mod/github.com/zondax/[email protected]/hid_enabled.go:22:11: fatal error: sys/poll.h: No such file or directory
  #include <sys/poll.h>
           ^~~~~~~~~~~~
compilation terminated.
Makefile:94: recipe for target 'install' failed

Ubuntu 18.04.1, x64 hardware, and go version go1.12.4 linux/amd64. While trying to make tools install https://github.com/cosmos/cosmos-sdk

Why not use hidraw instead of libusb?

Just asking - why does this use libusb instead of hidraw backend? Hidraw seems like less of a hassle (no need to package all libusb), but I have not tried it.

New module version tag

Hello,
When go-getting this module, it will by default download the latest tagged version (v1.0.0, 2019) which seems not to work on some platforms (tested on macOS 14.2.1, arm64), but works when getting the latest commit.
Could a newer version tag be created so the module works without having to point to a specific commit?
Thanks a lot! :)

Compile error on win7 64bit

$ go build

github.com/karalabe/hid

In file included from .\hid_enabled.go:40:
./hidapi/windows/hid.c: In function 'hid_enumerate':
./hidapi/windows/hid.c:431:5: warning: 'strncpy' specified bound depends on the length of the source argument [-Wstringop-overflow=]
strncpy(cur_dev->path, str, len+1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./hidapi/windows/hid.c:429:11: note: length computed here
len = strlen(str);
^~~~~~~~~~~

Device's Close method should implement io.Closer

Hello! I'm using hid in an upcoming project, and noticed that Device.Close has no return value. Since almost all Close functions in Go return an error, would it be acceptable to add an error return value to this method as well?

This would enable *hid.Device to easily implement io.Closer and io.ReadWriteCloser, and ensure that if any error return value is needed in the future, it can be easily adjusted.

Let me know what you think, and thank you for this package.

Doesn't seem to compile on Windows 10, mingw64

$ go get github.com/dh1tw/streamdeck
# github.com/karalabe/hid
In file included from ..\..\karalabe\hid\hid_enabled.go:40:
..\..\karalabe\hid/hidapi/windows/hid.c: In function 'hid_enumerate':
..\..\karalabe\hid/hidapi/windows/hid.c:431:5: warning: 'strncpy' specified bound depends on the length of the source argument [-Wstringop-overflow=]
     strncpy(cur_dev->path, str, len+1);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..\..\karalabe\hid/hidapi/windows/hid.c:429:11: note: length computed here
     len = strlen(str);
           ^~~~~~~~~~~

Mingw64 version:

$ choco info mingw
Chocolatey v0.10.8
mingw 8.1.0 [Approved] Downloads cached for licensed users
 Title: MinGW-w64 | Published: 30/10/2018
 Package approved by gep13 on Jun 30 2019 14:22:35.
 Package testing status: Passing on Oct 30 2018 18:40:10.
 Number of Downloads: 154896 | Downloads for this version: 24259
 Package url
 Chocolatey Package Source: n/a
 Package Checksum: 'ObzK15CYC2pW0gGFTFYMQWPSEYV8ono//ozdORZ23GBNY6XHUBFB5EN6gJl3gABZqD8ltzG8zdlGiEvaJ7zjLQ==' (SHA512)
 Tags: compiler gcc mingw mingw-w64
 Software Site: https://mingw-w64.org/
 Software License: n/a
 Summary: GCC for Windows 64 & 32 bits.
 Description: Mingw-w64 is an advancement of the original mingw.org project, created to support the GCC compiler on Windows systems. It has forked it in 2007 in order
to provide support for 64 bits and new APIs. It has since then gained widespread use and distribution.

Compile error on ubuntu18

# github.com/karalabe/hid
vendor/github.com/karalabe/hid/hid_enabled.go:23:11: fatal error: os/threads_posix.c: No such file or directory
  #include "os/threads_posix.c"
           ^~~~~~~~~~~~~~~~~~~~

Have been getting this on ubuntu18. CGO_ENABLED=1. libusb 1.0.0 + libusb1.0.0-dev installed.

Wondering what I'm missing

Support hid_read_timeout

There doesn't seem to be a sensible way to do a read that doesn't then block forever (and lock!)

Unknown failure on write

I'm trying to change the LED on my keyboard.
This is the snippet: https://pastebin.com/Xzr1X9P5

When I try to write more than 8btyes, I get an error: hidapi: unknown failure

I don't really know how to debug this.
I didn't really find any examples online, and I'm quite new to this stuff.
Any help is appreciated!

Question: USB HID Keyboard scan codes / ascii

Thanks for this nice golang package. I use it to connect to a second usb keyboard. I receive the bytes from the connected keyboard representing the scancodes. (like 4 for "a").

Do u know an easy way to map/convert the incoming scancodes to runes or characters to receive a string in the end (even using the current operating system keyboard layout). I have a loop reading all inputs only from the second keyboard, which works fine, until enter is pressed. But now i have only the "scancodes" but need to get an ascii string.

Thanks in advance.

Cross compile error in windows

this a simple demo code:

package main

import (
	"fmt"
	"time"
	"github.com/karalabe/hid"
)

func main() {
	vid, pid := uint16(0x16C0), uint16(0x05DF)
	devices := hid.Enumerate(vid, pid)
	if len(devices) == 0 {
		fmt.Println("未找到设备")
		return
	}
	device, err := devices[0].Open()
	if err != nil {
		fmt.Println("无法打开设备:", err)
		return
	}
	defer device.Close()

	channel := byte(1)
	state := byte(1) 

	buf := []byte{0x00, 0x00, 0xFF, channel, state}
	_, err = device.Write(buf)
	if err != nil {
		fmt.Println("无法写入数据:", err)
		return
	}

	time.Sleep(1 * time.Second)
}

linux cross compile for window:

CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOARM= go build -ldflags "-s -w" -o build/relay cmd/relay/main.go

runtime/cgo

gcc: error: unrecognized command line option ‘-mthreads’; did you mean ‘-pthread’?
make: *** [Makefile:10: relay] Error 1

windows cross compile for window:

C:\Users\lau\code\demo>mingw32-make.exe
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOARM= go build -ldflags "-s -w" -o build/relay cmd/relay/main.go

github.com/karalabe/hid

In file included from ........\go\pkg\mod\github.com\karalabe\[email protected]\hid_enabled.go:40:
........\go\pkg\mod\github.com\karalabe\[email protected]/hidapi/windows/hid.c: In function 'hid_enumerate':
........\go\pkg\mod\github.com\karalabe\[email protected]/hidapi/windows/hid.c:431:5: warning: 'strncpy' specified bound depends on the length of the source argument [-Wstringop-overflow=]
strncpy(cur_dev->path, str, len+1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
........\go\pkg\mod\github.com\karalabe\[email protected]/hidapi/windows/hid.c:429:11: note: length computed here
len = strlen(str);
^~~~~~~~~~~

How to resolve ? think you

Deprecation warnings when building on macOS 12.0

When running go tests or vet, warnings pop up similar to those described here: karalabe/usb#25

# github.com/karalabe/hid
In file included from vendor/github.com/karalabe/hid/hid_enabled.go:38:
vendor/github.com/karalabe/hid/hidapi/mac/hid.c:693:34: warning: 'kIOMasterPortDefault' is deprecated: first deprecated in macOS 12.0 [-Wdeprecated-declarations]
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/IOKit.framework/Headers/IOKitLib.h:123:19: note: 'kIOMasterPortDefault' has been explicitly marked deprecated here

wchar.go:44:8: error: enumerator value for '__cgo_enum__0' is not an integer constant

Hi. I am building the latest release of geth which depends on hid. Unfortunately, I have the topic error, more of it below. Probably, it is a build environment problem (I'm using NixOS linux distro which is quite unusual).
My go is version 1.7.1.
Could you please suggest a hint regarding the error?

# github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:44:8: error: enumerator value for '__cgo_enum__0' is not an integer constant
   return stringToWchar4(s) // Unix       
        ^                                 
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:52:8: error: enumerator value for '__cgo_enum__7' is not an integer constant
  case 2:                                 
        ^                                 
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:60:2: error: initializer element is not constant
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:60:2: note: (near initialization for '__cgodebug_data[0]')
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:67:2: error: initializer element is not constant
  default:                                
  ^                                       
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:67:2: note: (near initialization for '__cgodebug_data[7]')
github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid
# github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:44:8: error: enumerator value for '__cgo_enum__0' is not an integer constant
   return stringToWchar4(s) // Unix       
        ^                                 
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:52:8: error: enumerator value for '__cgo_enum__7' is not an integer constant
  case 2:                                 
        ^                                 
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:60:2: error: initializer element is not constant
go/src/github.com/ethereum/go-ethereum/vendor/github.com/karalabe/hid/wchar.go:60:2: note: (near initialization for '__cgodebug_data[0]')

hid_read or hid_get_feature_report?

OS: Windows 10 Version 1709
For my device, hid_read is not working but hid_get_feature_report is. I can't figure out the reason but after wrapping hid_get_feature_report in your package. My program can read data from device. I am not a driver developer so I don't have much experience on how to debug this problem.

could not determine kind of name for C.** under window 7 (32bit)

C:\Users\Frank>go install github.com/karalabe/hid

github.com/karalabe/hid

d:\go\src\github.com\karalabe\hid\hid_enabled.go:133:10: could not determine kind of name for C.hid_device
d:\go\src\github.com\karalabe\hid\hid_enabled.go:174:61: could not determine kind of name for C.size_t
d:\go\src\github.com\karalabe\hid\hid_enabled.go:174:39: could not determine kind of name for C.uchar
d:\go\src\github.com\karalabe\hid\hid_enabled.go:82:26: could not determine kind of name for C.ushort
`

C:\Users\Frank>go get github.com/karalabe/hid

github.com/karalabe/hid

d:\go\src\github.com\karalabe\hid\hid_enabled.go:133:10: could not determine kind of name for C.hid_device
d:\go\src\github.com\karalabe\hid\hid_enabled.go:174:61: could not determine kind of name for C.size_t
d:\go\src\github.com\karalabe\hid\hid_enabled.go:174:39: could not determine kind of name for C.uchar
d:\go\src\github.com\karalabe\hid\hid_enabled.go:82:26: could not determine kind of name for C.ushort

usage in trezord

Hello,

this is not an issue, just a thanks/letting you know that we will use this library (and xgo library) in trezord, which we are now rewriting from c++ to go. (it seems you are working on geth, so you know what is trezor :D)

See

(if you are interested - we need both libusb directly and hidapi, because we will switch from hidapi to webusb soon-ish and we want to support both)

Cross-compilation Go and Goc "symbol not found" error message on ARM

I'm trying to build a Go program for my LinkSys MR8300 V1.1 router, which has armv7l processor (uname -a output), which is ARM v7, 32-bit CPU. I have OpenWrt operating system installed on the router.

The idea of the app is to connect USB coin acceptor, and enable internet for 30 minutes when you drop a coin. I have working app on the Ubuntu desktop which understands the device, and on desktop everything's fine.

However, the router is 32 bit, and ARM, so things are little bit different and more complicated.

cat /proc/cpuinfo on my router gives something like this:

processor       : 0
model name      : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 26.81
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5

I'm using cross-compilation, since the router has only 19MB of disk space (and not all of the development packages are available).

For cross-compilation I'm using x86_64 Ubuntu desktop, and toolchain provided by OpenWrt. I'm already past the point when you need to configure and make the toolchain. I was able to compile and execute the basic C programs on my router, like:

#include <stdio.h>

int main()
{
  printf("Hello World");
  return 0;
}

And even Go programs like:

package main

func main() {
        println("Coin acceptor device control program")
}

When I upload binaries to the router they work, there is no any problem with that.

Problems start when I try to use USB library inside the router. Since it's cross-compilation, I should mention environment variables I have:

STAGING_DIR=/home/ro/work/openwrt/staging_dir
TOOLCHAIN_DIR=/home/ro/work/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-11.3.0_musl_eabi
LDCFLAGS=/home/ro/work/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-11.3.0_musl_eabi/usr/lib
LD_LIBRARY_PATH=/home/ro/work/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-11.3.0_musl_eabi/usr/lib
LDFLAGS=-L/home/ro/work/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-11.3.0_musl_eabi/usr/lib
CGO_LDFLAGS=-L/home/ro/work/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-11.3.0_musl_eabi/usr/lib
CFLAGS=-I/home/ro/work/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-11.3.0_musl_eabi/include
CC=arm-openwrt-linux-gcc
GOARCH=arm
CROSS_COMPILE=arm-openwrt-linux-gcc
CGO_ENABLED=1
GOOS=linux
GOARM=7

With these environment variables go get github.com/karalabe/hid command works as expected (there is hid.a binary in my /home/ro/go/pkg/linux_arm/github.com/karalabe folder).

However, this library has dependencies on some C libraries... So here is where GOC comes into play I guess.

As I mentioned before, I can compile simple apps on my Desktop and upload them to the router, and these apps work! However, when I try to use the library, things go little bit off the script.

Here is the app I have:

main.go

package main

import (
        "fmt"
)

func main() {
        println("Hello")

        devices := FindAll(0x0079)

        if len(devices) == 0 {
                fmt.Println("No coin acceptor found")
                return
        }

        println("Found coin acceptor")
}

device.go

package main

import (
	"errors"
	"github.com/karalabe/hid"
)

type Device struct {
	info hid.DeviceInfo
	dev  *hid.Device

	Name string
	PID  uint16
}

func (device *Device) Open() error {
	if device.dev != nil {
		return errors.New("device: Device handle is not null, but Open() called")
	}

	var err error
	device.dev, err = device.info.Open()

	return err
}

func (device *Device) Close() error {
	if device.dev == nil {
		return errors.New("device: Close() called for Device with null handle")
	}

	err := device.dev.Close()
	device.dev = nil

	return err
}

// Find all products with the given product ID.
func FindAll(product uint16) []Device {
	deviceInfo := hid.Enumerate(0x1e7d, product)

	if len(deviceInfo) == 0 {
		return []Device{}
	}

	devices := make([]Device, len(deviceInfo))

	for i, info := range deviceInfo {
		devices[i] = Device{
			info: info,
			Name: info.Product,
			PID:  product,
		}
	}

	return devices
}

Command I use to build a thing:

go build ./main.go ./device.go

The binary gets produced, and things look normal. Until the point when I upload and run the binary on the router. It pretty much says:

Error relocating ./main: __pthread_cond_timedwait_time64: symbol not found
Error relocating ./main: __nanosleep_time64: symbol not found
Error relocating ./main: __stat_time64: symbol not found
Error relocating ./main: __clock_gettime64: symbol not found

And that's it. It doesn't even print "Hello".

One thing to notice is that it has references to (and complains about) 64-bit functions for some reason. So, to sum this up:

  • This is 32-bit ARM CPU.
  • I can run simple C and Go programs, so I assume that my C and Go compiles provide correct binaries for the 32-bit CPU.
  • When I try to attach the library none of the compilers (I assume the app gets compiled using Go and Goc) complains about using 64-bit functions.
  • The binary itself complains about 64-bit functions.

I'm wondering what am I missing? What flags should I specify to the compiler(s) so there is no 64-bit functions usage? Maybe there is something inside these USB libraries written in C? I kinda ran out of any ideas and pretty much stuck at this point, since I cannot use my USB device with embedded OpenWrt device.

Couldn't open Ledger nano S on Mac Sonoma (chip M1 max)

I tried with this minimal test program:

package main

import (
	"fmt"

	"github.com/karalabe/hid"
)

func main() {
	// Ledger Nano S Vendor ID and Product ID
	vendorID := uint16(0x2c97)
	productID := uint16(0x1015)

	// Enumerate devices to find the Ledger
	devices := hid.Enumerate(vendorID, productID)
	if len(devices) == 0 {
		fmt.Println("No Ledger Nano S found.")
		return
	}

	// Open the first found Ledger device
	device, err := devices[0].Open()
	if err != nil {
		fmt.Printf("Failed to open device: %v\n", err)
		return
	}
	defer device.Close()
	fmt.Println("Device successfully opened.")
}

Output:

Failed to open device: hidapi: failed to open device

While it is possible to open/connect using homebrew's hidapi like this:

package main

/*
#cgo CFLAGS: -I/opt/homebrew/Cellar/hidapi/0.14.0/include/hidapi
#cgo LDFLAGS: -L/opt/homebrew/Cellar/hidapi/0.14.0/lib -lhidapi
#include <hidapi.h>
*/
import "C"
import (
	"fmt"
)

func main() {
	// Initialize the HIDAPI library
	res := C.hid_init()
	if res != 0 {
		fmt.Println("Failed to initialize HIDAPI")
		return
	}
	defer C.hid_exit()

	// Open the device using Vendor ID and Product ID
	vendorID := C.ushort(0x2c97)
	productID := C.ushort(0x1015)
	device := C.hid_open(vendorID, productID, nil)
	if device == nil {
		fmt.Println("Failed to open device")
		return
	}
	defer C.hid_close(device)

	// Your HID interaction code here
	fmt.Println("Device opened successfully")
}

Output:

Device opened successfully

libusb is under LGPL, not GPL

your LICENSE.md and README.md files state that libusb is under GPL 2.1, which is wrong. the COPYING file states

GNU LESSER GENERAL PUBLIC LICENSE

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.