Beispiel #1
0
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
}
Beispiel #4
0
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

}
Beispiel #5
0
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")
		}
	}
}
Beispiel #6
0
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()
}