func registerInterrupt(pin *digitalPin, handler func(embd.DigitalPin)) error { l := getEpollListenerInstance() pinFd := int(pin.val.Fd()) l.mu.Lock() defer l.mu.Unlock() if _, ok := l.interruptablePins[pinFd]; ok { return ErrorPinAlreadyRegistered } var event syscall.EpollEvent event.Events = syscall.EPOLLIN | (syscall.EPOLLET & 0xffffffff) | syscall.EPOLLPRI if err := syscall.SetNonblock(pinFd, true); err != nil { return err } event.Fd = int32(pinFd) if err := syscall.EpollCtl(l.fd, syscall.EPOLL_CTL_ADD, pinFd, &event); err != nil { return err } l.interruptablePins[pinFd] = &interrupt{pin: pin, handler: handler} return nil }
func (p *pollster) StopWaiting(fd int, bits uint) { events, already := p.events[fd] if !already { print("Epoll unexpected fd=", fd, "\n") return } // If syscall.EPOLLONESHOT is not set, the wait // is a repeating wait, so don't change it. if events&syscall.EPOLLONESHOT == 0 { return } // Disable the given bits. // If we're still waiting for other events, modify the fd // event in the kernel. Otherwise, delete it. events &= ^uint32(bits) if int32(events)&^syscall.EPOLLONESHOT != 0 { var ev syscall.EpollEvent ev.Fd = int32(fd) ev.Events = events if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &ev); e != 0 { print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n") } p.events[fd] = events } else { if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 { print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n") } p.events[fd] = 0, false } }
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error { var ev syscall.EpollEvent var already bool ev.Fd = int32(fd) ev.Events, already = p.events[fd] if !repeat { ev.Events |= syscall.EPOLLONESHOT } if mode == 'r' { ev.Events |= readFlags } else { ev.Events |= writeFlags } var op int if already { op = syscall.EPOLL_CTL_MOD } else { op = syscall.EPOLL_CTL_ADD } if e := syscall.EpollCtl(p.epfd, op, fd, &ev); e != 0 { return os.NewSyscallError("epoll_ctl", e) } p.events[fd] = ev.Events return nil }
func (p *pin) BeginWatch(edge Edge, callback IRQEvent) error { p.SetMode(ModeInput) if err := write([]byte(edge), p.edgePath); err != nil { return err } var event syscall.EpollEvent event.Events = syscall.EPOLLIN | (syscall.EPOLLET & 0xffffffff) | syscall.EPOLLPRI fd := int(p.valueFile.Fd()) p.callback = callback watchEventCallbacks[fd] = p if err := syscall.SetNonblock(fd, true); err != nil { return err } event.Fd = int32(fd) if err := syscall.EpollCtl(epollFD, syscall.EPOLL_CTL_ADD, fd, &event); err != nil { return err } return nil }
func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { var family int var ra, la syscall.Sockaddr ip, err := net.ResolveIPAddr("ip", host) if err != nil { return nil, fmt.Errorf("invalid ip: %s", err) } l, err := net.ResolveIPAddr("ip", localAddr) if l == nil { return nil, fmt.Errorf("invalid local ip: %s", err) } if (ip.IP.To4() != nil) != (l.IP.To4() != nil) { return nil, fmt.Errorf("remote and local ip address family is not same") } switch { case ip.IP.To4() != nil: family = syscall.AF_INET i := &syscall.SockaddrInet4{ Port: port, } for idx, _ := range i.Addr { i.Addr[idx] = ip.IP.To4()[idx] } ra = i j := &syscall.SockaddrInet4{} for idx, _ := range j.Addr { j.Addr[idx] = l.IP.To4()[idx] } la = j default: family = syscall.AF_INET6 i := &syscall.SockaddrInet6{ Port: port, } for idx, _ := range i.Addr { i.Addr[idx] = ip.IP[idx] } ra = i var zone uint32 if l.Zone != "" { intf, err := net.InterfaceByName(l.Zone) if err != nil { return nil, err } zone = uint32(intf.Index) } j := &syscall.SockaddrInet6{ ZoneId: zone, } for idx, _ := range j.Addr { j.Addr[idx] = l.IP[idx] } la = j } sotype := syscall.SOCK_STREAM | syscall.SOCK_CLOEXEC | syscall.SOCK_NONBLOCK proto := 0 fd, err := syscall.Socket(family, sotype, proto) if err != nil { return nil, err } fi := os.NewFile(uintptr(fd), "") defer fi.Close() t, err := buildTcpMD5Sig(host, key) if err != nil { return nil, err } if _, _, e := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(syscall.IPPROTO_TCP), uintptr(TCP_MD5SIG), uintptr(unsafe.Pointer(&t)), unsafe.Sizeof(t), 0); e > 0 { return nil, os.NewSyscallError("setsockopt", e) } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { return nil, os.NewSyscallError("setsockopt", err) } if err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil { return nil, os.NewSyscallError("setsockopt", err) } if err = syscall.Bind(fd, la); err != nil { return nil, os.NewSyscallError("bind", err) } tcpconn := func(fi *os.File) (*net.TCPConn, error) { conn, err := net.FileConn(fi) return conn.(*net.TCPConn), err } err = syscall.Connect(fd, ra) switch err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: // do timeout handling case nil, syscall.EISCONN: return tcpconn(fi) default: return nil, os.NewSyscallError("connect", err) } epfd, e := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if e != nil { return nil, e } defer syscall.Close(epfd) var event syscall.EpollEvent events := make([]syscall.EpollEvent, 1) event.Events = syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLPRI event.Fd = int32(fd) if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil { return nil, e } for { nevents, e := syscall.EpollWait(epfd, events, msec) if e != nil { return nil, e } if nevents == 0 { return nil, fmt.Errorf("timeout") } else if nevents == 1 && events[0].Fd == int32(fd) { nerr, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { return nil, os.NewSyscallError("getsockopt", err) } switch err := syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case syscall.Errno(0), syscall.EISCONN: return tcpconn(fi) default: return nil, os.NewSyscallError("getsockopt", err) } } else { return nil, fmt.Errorf("unexpected epoll behavior") } } }
func (watcher *PinWatcher) pinHandler() { exf, exf_err := os.OpenFile("/sys/class/gpio/export", syscall.O_WRONLY, 0400) if exf_err != nil { log.Panicln("Error opening /sys/class/gpio/export:", exf_err) } _, ex_err := exf.WriteString(fmt.Sprintf("%d", watcher.pin)) if ex_err != nil { log.Panicln("Error writing to /sys/class/gpio/export:", ex_err) } exf.Close() time.Sleep(time.Microsecond) edge_file := fmt.Sprintf("/sys/class/gpio/gpio%d/edge", watcher.pin) edgef, edgef_err := os.OpenFile(edge_file, syscall.O_WRONLY, 0400) if edgef_err != nil { log.Panicf("Error opening %s: %s\n", edge_file, edgef_err) } _, edge_err := edgef.WriteString("both") if edge_err != nil { log.Panicf("Error writing to %s: %s\n", edge_file, edge_err) } edgef.Close() time.Sleep(time.Microsecond) value_file := fmt.Sprintf("/sys/class/gpio/gpio%d/value", watcher.pin) irq_fd, irq_err := syscall.Open(value_file, syscall.O_RDONLY|syscall.O_NONBLOCK, syscall.S_IREAD) if irq_err != nil { log.Panicln("Error opening %s: %s\n", value_file, irq_err) } epfd, eperr := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC) if eperr != nil { log.Panicln("Error creating epoll:", eperr) } event := new(syscall.EpollEvent) event.Fd = int32(irq_fd) event.Events |= syscall.EPOLLPRI if ctlerr := syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, irq_fd, event); ctlerr != nil { log.Panicln("Error on epoll control operation:", ctlerr) } var events_buffer [10]syscall.EpollEvent var buf [1]byte for !watcher.shutdown { n, werr := syscall.EpollWait(epfd, events_buffer[0:], 4000) if werr != nil { log.Println("Epoll error:", werr) } else if n == 1 { syscall.Seek(irq_fd, 0, 0) syscall.Read(irq_fd, buf[0:]) log.Println("Interrupt!", events_buffer[0].Fd, events_buffer[0].Events, buf) } else { log.Println("Timeout") } } syscall.Close(irq_fd) unexf, unexf_err := os.OpenFile("/sys/class/gpio/unexport", syscall.O_WRONLY|syscall.O_SYNC, 0400) if unexf_err != nil { log.Panicln("Error opening /sys/class/gpio/unexport:", unexf_err) } _, unex_err := unexf.WriteString(fmt.Sprintf("%d", watcher.pin)) if unex_err != nil { log.Panicln("Error writing to /sys/class/gpio/unexport:", unex_err) } unexf.Close() watcher.wg.Done() }