From ad36001a4d241c5710c5bedb78ce2b498f3c63c4 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 12:52:42 +0200 Subject: [PATCH 1/9] parts/usbip initial bridge avr_usb to a usbip attached device --- examples/parts/usb_types.h | 70 +++++ examples/parts/usbip.c | 546 +++++++++++++++++++++++++++++++++ examples/parts/usbip.h | 35 +++ examples/parts/usbip_tester.py | 261 ++++++++++++++++ examples/parts/usbip_types.h | 150 +++++++++ 5 files changed, 1062 insertions(+) create mode 100644 examples/parts/usb_types.h create mode 100644 examples/parts/usbip.c create mode 100644 examples/parts/usbip.h create mode 100755 examples/parts/usbip_tester.py create mode 100644 examples/parts/usbip_types.h diff --git a/examples/parts/usb_types.h b/examples/parts/usb_types.h new file mode 100644 index 000000000..182cd2f7d --- /dev/null +++ b/examples/parts/usb_types.h @@ -0,0 +1,70 @@ +#include + +#define byte uint8_t +#define word uint16_t + +struct usb_setup_pkt { + byte reqtype; + byte req; + word wValue; + word wIndex; + word wLength; +} __attribute__((__packed__)); + +#define USB_REQTYPE_DIR_DEV_TO_HOST 0x80 +#define USB_REQTYPE_STD 0 +#define USB_REQTYPE_DEVICE 0 + +#define USB_REQUEST_GET_DESCRIPTOR 0x06 + + +// USB Descriptors +#define USB_DESCRIPTOR_DEVICE 0x01 // Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // Device Qualifier. + +struct usb_device_descriptor { + byte bLength; // Length of this descriptor. + byte bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + word bcdUSB; // USB Spec Release Number (BCD). + byte bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + byte bDeviceSubClass; // Subclass code (assigned by the USB-IF). + byte bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + byte bMaxPacketSize0; // Maximum packet size for endpoint 0. + word idVendor; // Vendor ID (assigned by the USB-IF). + word idProduct; // Product ID (assigned by the manufacturer). + word bcdDevice; // Device release number (BCD). + byte iManufacturer; // Index of String Descriptor describing the manufacturer. + byte iProduct; // Index of String Descriptor describing the product. + byte iSerialNumber; // Index of String Descriptor with the device's serial number. + byte bNumConfigurations; // Number of possible configurations. +} __attribute__ ((__packed__)); + +struct usb_configuration_descriptor +{ + byte bLength; // Length of this descriptor. + byte bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + word wTotalLength; // Total length of all descriptors for this configuration. + byte bNumInterfaces; // Number of interfaces in this configuration. + byte bConfigurationValue; // Value of this configuration (1 based). + byte iConfiguration; // Index of String Descriptor describing the configuration. + byte bmAttributes; // Configuration characteristics. + byte bMaxPower; // Maximum power consumed by this configuration. +} __attribute__ ((__packed__)); + + +struct usb_interface_descriptor +{ + byte bLength; // Length of this descriptor. + byte bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + byte bInterfaceNumber; // Number of this interface (0 based). + byte bAlternateSetting; // Value of this alternate interface setting. + byte bNumEndpoints; // Number of endpoints in this interface. + byte bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + byte bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + byte bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + byte iInterface; // Index of String Descriptor describing the interface. +} __attribute__ ((__packed__)); diff --git a/examples/parts/usbip.c b/examples/parts/usbip.c new file mode 100644 index 000000000..06d40d32f --- /dev/null +++ b/examples/parts/usbip.c @@ -0,0 +1,546 @@ +/* vim: set sts=4:sw=4:ts=4:noexpandtab + usbip.c + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr 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. + + simavr 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 simavr. If not, see . + + + This code is heavily inspired by + https://github.com/lcgamboa/USBIP-Virtual-USB-Device + Copyright (c) : 2016 Luis Claudio Gambôa Lopes +*/ + +/* + this avrsim part will expose your usb-avr as a usbip server. + To connect it to the host system load modules usbip-core and vhci-hcd, + then: + ~# usbip -a 127.0.0.1 1-1 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define USBIP_PORT_NUM 3240 + +#include "usb_types.h" +#include "usbip_types.h" + +#include "avr_usb.h" + +#define min(a,b) ((a)<(b)?(a):(b)) + +struct usbip_t { + struct avr_t * avr; + bool attached; + bool udev_valid; + struct usbip_usb_device udev; +}; + +static ssize_t +avr_usb_read( + const struct usbip_t * p, + unsigned int ep, + void * buf, + size_t blen) +{ + byte * b = buf; + struct avr_io_usb pkt = { ep, blen, b }; + if (buf) { + while (blen) { + switch (avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt)) { + case AVR_IOCTL_USB_NAK: + if (pkt.buf - b == 0) return -1; + else return pkt.buf - b; + case AVR_IOCTL_USB_STALL: + printf(" STALL (read)\n"); + return -1; + case 0: + if (!pkt.sz) + blen = 0; + break; + default: + fprintf(stderr, "Unknown avr_ioctl return value\n"); + abort(); + } + pkt.buf += pkt.sz & 0xff; + blen -= pkt.sz & 0xff; + if (pkt.sz & 0xf00) break; + pkt.sz = blen; + } + return pkt.buf - b; + } else { + int ret; + while ((ret = avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt)) + == AVR_IOCTL_USB_NAK) { + usleep(50000); + } + return 0; + } +} + +static int +avr_usb_write( + const struct usbip_t * p, + unsigned int ep, + void * buf, + size_t blen) +{ + struct avr_io_usb pkt = { ep, blen, buf }; + do { + switch (avr_ioctl(p->avr, AVR_IOCTL_USB_WRITE, &pkt)) { + case 0: break; + case AVR_IOCTL_USB_NAK: + if (buf) return -1; + usleep(50000); + continue; + case AVR_IOCTL_USB_STALL: + printf(" STALL (write)\n"); + return -1; + default: + fprintf(stderr, "Unknown avr_ioctl return\n"); + abort(); + } + pkt.buf += pkt.sz; + blen -= pkt.sz; + pkt.sz = blen; + if (!blen) break; + } while (1); + return 0; +} + +static int +control_read( + const struct usbip_t * p, + byte reqtype, + byte req, + word wValue, + word wIndex, + word wLength, + byte * data) +{ + int ret; + struct usb_setup_pkt buf = { + reqtype | USB_REQTYPE_DIR_DEV_TO_HOST, + req, + wValue, + wIndex, + wLength }; + const unsigned int ctrlep = 0; + struct avr_io_usb pkt = { ctrlep, sizeof buf, (uint8_t*) &buf }; + + printf("ctrl_read typ:%d req:%d val:%04x len:%d bytes\n", reqtype, req, wValue, wLength); + avr_ioctl(p->avr, AVR_IOCTL_USB_SETUP, &pkt); + + ret = avr_usb_read(p, ctrlep, data, wLength); + + avr_usb_write(p, ctrlep, NULL, 0); + + return ret; +} + +static bool +get_descriptor( + const struct usbip_t * p, + unsigned char descr_type, + void * buf, + size_t length) +{ + const unsigned char descr_index = 0; + return control_read(p, + USB_REQTYPE_STD + USB_REQTYPE_DEVICE, + USB_REQUEST_GET_DESCRIPTOR, + descr_type << 8 | descr_index, + 0, + length, + buf) == (int)length; +} + +static bool +load_device_and_config_descriptor( + struct usbip_t * p) +{ + struct usb_device_descriptor dd; + struct usb_configuration_descriptor cd; + if (!get_descriptor(p, USB_DESCRIPTOR_DEVICE, &dd, sizeof dd)) { + fprintf(stderr, "get device descriptor failed\n"); + p->udev_valid = false; + return false; + } + + if (!get_descriptor(p, USB_DESCRIPTOR_CONFIGURATION, &cd, sizeof cd)) { + fprintf(stderr, "get configuration descriptor failed\n"); + p->udev_valid = false; + return false; + } + + strcpy(p->udev.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1"); + strcpy(p->udev.busid, "1-1"); + p->udev.busnum = htonl(1); + p->udev.devnum = htonl(2); + p->udev.speed = htonl(2); + + p->udev.idVendor = htons(dd.idVendor); + p->udev.idProduct = htons(dd.idProduct); + p->udev.bcdDevice = htons(dd.bcdDevice); + + p->udev.bDeviceClass = dd.bDeviceClass; + p->udev.bDeviceSubClass = dd.bDeviceSubClass; + p->udev.bDeviceProtocol = dd.bDeviceProtocol; + p->udev.bConfigurationValue = cd.bConfigurationValue; + p->udev.bNumConfigurations = dd.bNumConfigurations; + p->udev.bNumInterfaces = cd.bNumInterfaces; + + p->udev_valid = true; + return true; +} + + +static void +vhci_usb_attach_hook( + struct avr_irq_t * irq, + uint32_t value, + void * param) +{ + struct usbip_t * p = param; + p->attached = !!value; + printf("avr attached: %d\n", p->attached); + + avr_ioctl(p->avr, AVR_IOCTL_USB_VBUS, (void*) 1); + + (void)irq; +} + +static int sock_read_exact( + int sockfd, + void * buf, + size_t n) +{ + while (n != 0) { + ssize_t nb = recv(sockfd, buf, n, 0); + if (nb == 0) { + fprintf(stderr, "disconnect\n"); + return 1; + } + if (nb < 0) { + perror("sock_read_exact"); + return -1; + } + n -= nb; + } + return 0; +} + +static int +open_usbip_socket(void) +{ + struct sockaddr_in serv; + int listenfd; + + if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket error"); + exit (1); + }; + + int reuse = 1; + if (setsockopt( + listenfd, + SOL_SOCKET, + SO_REUSEADDR, + (const char*)&reuse, + sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); + + memset(&serv, 0, sizeof serv); + serv.sin_family = AF_INET; + serv.sin_addr.s_addr = htonl(INADDR_ANY); + serv.sin_port = htons(USBIP_PORT_NUM); + + if (bind(listenfd, (struct sockaddr *)&serv, sizeof serv) < 0) { + perror("bind error"); + exit (1); + } + + if (listen(listenfd, SOMAXCONN) < 0) { + perror("listen error"); + exit (1); + } + + return listenfd; +} + + +#define sock_send(sockfd, dta, dta_sz) if(send(sockfd, dta, dta_sz, 0) != dta_sz) { perror("sock send"); break; } +static void +handle_usbip_req_devlist( + int sockfd, + struct usbip_t * p) +{ + struct usbip_op_common op_common = { + htons(USBIP_PROTO_VERSION), + htons(USBIP_OP_REPLY | USBIP_OP_DEVLIST), + htonl(USBIP_ST_NA) + }; + struct usbip_op_devlist_reply devlist = {htonl(1)}; + + + avr_ioctl(p->avr, AVR_IOCTL_USB_RESET, NULL); + usleep(2500); + + load_device_and_config_descriptor(p); + + // get config AND interface descriptors + struct { + struct usb_configuration_descriptor config; + struct usb_interface_descriptor interf[p->udev.bNumInterfaces]; + } cd; + if (!get_descriptor(p, USB_DESCRIPTOR_CONFIGURATION, &cd, sizeof cd)) { + fprintf(stderr, "get configuration descriptor failed\n"); + if (send(sockfd, &op_common, sizeof op_common, 0) != sizeof op_common) + perror("sock send"); + return; + } + + ssize_t devinfo_sz = sizeof (struct usbip_usb_device) + + p->udev.bNumInterfaces * sizeof (struct usbip_usb_interface); + struct usbip_op_devlist_reply_extra * devinfo = malloc(devinfo_sz); + + devinfo->udev = p->udev; + + for (byte i=0; i < devinfo->udev.bNumInterfaces; i++) { + devinfo->uinf[i].bInterfaceClass = cd.interf[i].bInterfaceClass; + devinfo->uinf[i].bInterfaceSubClass = cd.interf[i].bInterfaceSubClass; + devinfo->uinf[i].bInterfaceProtocol = cd.interf[i].bInterfaceProtocol; + devinfo->uinf[i].padding = 0; + } + + op_common.status = htonl(USBIP_ST_OK); + + do { + sock_send(sockfd, &op_common, sizeof op_common) + sock_send(sockfd, &devlist, sizeof devlist) + sock_send(sockfd, devinfo, devinfo_sz) + } while (0); + + free(devinfo); +} + +static int +handle_usbip_detached_state( + int sockfd, + struct usbip_t * p) +{ + struct usbip_op_common op_common; + if (sock_read_exact(sockfd, &op_common, sizeof op_common)) + return -1; + unsigned version = ntohs(op_common.version); + unsigned op_code = ntohs(op_common.code); + + if (version != USBIP_PROTO_VERSION) { + fprintf(stderr, "Protocol version mismatch, request: %x, this: %x\n", + version, USBIP_PROTO_VERSION); + return -1; + } + printf("executing %d\n", op_code); + switch (op_code) { + case USBIP_OP_REQUEST | USBIP_OP_DEVLIST: + handle_usbip_req_devlist(sockfd, p); + break; + case USBIP_OP_REQUEST | USBIP_OP_IMPORT: { + struct usbip_op_import_request req; + if (recv(sockfd, &req, sizeof req, 0) != sizeof req) { + fprintf(stderr, "protocol vialation\n"); + return -1; + } + + avr_ioctl(p->avr, AVR_IOCTL_USB_RESET, NULL); + usleep(2500); + + + if (!load_device_and_config_descriptor(p)) { + printf("Failed load_Decice_And_config while attach\n"); + op_common.status = USBIP_ST_NA; + if (send(sockfd, &op_common, sizeof op_common, 0) != sizeof op_common) + perror("sock send"); + } else { + op_common.code = htons(USBIP_OP_REPLY | USBIP_OP_IMPORT), + op_common.status = USBIP_ST_OK; + struct usbip_op_import_reply reply = { p->udev }; + do { + sock_send(sockfd, &op_common, sizeof op_common) + sock_send(sockfd, &reply, sizeof reply) + } while(0); + } + printf("Attached to usbip client\n"); + return 1; + } + default: + fprintf(stderr, "Unknown usbip %s %x\n", + op_code & USBIP_OP_REQUEST ? "request" : "reply", + op_code & 0xff); + return -1; + } + return 0; +} + +static void +handle_usbip_connection( + int sockfd, + struct usbip_t * p) +{ + bool attached = false; + while (1) { + if (attached) { + struct usbip_header cmd; + if (sock_read_exact(sockfd, &cmd, sizeof cmd.hdr)) + return; + + byte ep = ntohl(cmd.hdr.ep); + int cmdnum = ntohl(cmd.hdr.command); + int direction = ntohl(cmd.hdr.direction); + + switch (cmdnum) { + case USBIP_CMD_SUBMIT: { + if (sock_read_exact(sockfd, &cmd.u.submit, sizeof cmd.u.submit)) + return; + ssize_t bl = ntohl(cmd.u.submit.transfer_buffer_length); + byte buf[bl]; + + if (ep == 0) { + struct avr_io_usb pkt = { ep, sizeof cmd.u.submit.setup, cmd.u.submit.setup }; + if (avr_ioctl(p->avr, AVR_IOCTL_USB_SETUP, &pkt)) { + printf("FATAL: SETUP packet failed!\n"); + } + } + + if (direction == USBIP_DIR_IN) { + if (bl) { + bl = avr_usb_read(p, ep, buf, bl); + if (ep==4 && bl < 0) bl = 0; //teensy & linux hack? + } + if (ep == 0) + avr_usb_write(p, ep, NULL, 0); + } else { + if (bl && sock_read_exact(sockfd, buf, bl)) + return; + if (bl) + bl = avr_usb_write(p, ep, buf, bl); + if (ep == 0) + avr_usb_read(p, ep, NULL, 0); + } + + + struct usbip_header ret; + memset(&ret, 0, sizeof ret); + ret.hdr.command = htonl(USBIP_RET_SUBMIT); + ret.hdr.seqnum = cmd.hdr.seqnum; + ret.u.retsubmit.status = htonl(bl < 0 ? USBIP_ST_NA : USBIP_ST_OK); + ret.u.retsubmit.actual_length = htonl(bl < 0 ? 0 : bl); + ret.u.retsubmit.start_frame = 0; + ret.u.retsubmit.number_of_packets = 0; + ret.u.retsubmit.error_count = 0; + memcpy(&ret.u.retsubmit.setup, cmd.u.submit.setup, 8); + +// printf("return %zd bytes\n", bl); + if (send(sockfd, &ret, sizeof ret.hdr + sizeof ret.u.retsubmit, 0) != sizeof ret.hdr + sizeof ret.u.retsubmit) + perror("sock send"); + if (bl>0 && send(sockfd, buf, bl, 0) != bl) + perror("sock send"); + +// printf("done\n"); + + + break; + } + case USBIP_CMD_UNLINK: + if (recv(sockfd, &cmd.u.unlink, sizeof cmd.u.unlink, 0) != sizeof cmd.u.unlink) { + perror("sock_recv"); + return; + } + break; + default: + fprintf(stderr, "protocol vialation, unknown command %x\n", ntohl(cmd.hdr.command)); + + } + + } else { + switch (handle_usbip_detached_state(sockfd, p)) { + case -1: return; + case 1: + attached = true; + default: + break; + } + } + } +} + +void * +usbip_main( + struct usbip_t * p) +{ + int listenfd = open_usbip_socket(); + struct sockaddr_in cli; + unsigned int clilen = sizeof(cli); + + while (1) { + int sockfd = accept(listenfd, (struct sockaddr *)&cli, &clilen); + + if ( sockfd < 0) { + printf ("accept error : %s \n", strerror (errno)); + exit (1); + } + fprintf(stderr, "Connection address:%s\n",inet_ntoa(cli.sin_addr)); + handle_usbip_connection(sockfd, p); + close(sockfd); + } + +(void)p; + return NULL; +} + + +struct usbip_t * +usbip_create( + struct avr_t * avr) +{ + struct usbip_t * p = malloc(sizeof *p); + memset(p, 0, sizeof *p); + p->avr = avr; + + avr_irq_t * t = avr_io_getirq(p->avr, AVR_IOCTL_USB_GETIRQ(), USB_IRQ_ATTACH); + avr_irq_register_notify(t, vhci_usb_attach_hook, p); + + return p; +} + +void +usbip_destroy( + void * p) +{ + free(p); +} +#undef sock_send diff --git a/examples/parts/usbip.h b/examples/parts/usbip.h new file mode 100644 index 000000000..ea25caed2 --- /dev/null +++ b/examples/parts/usbip.h @@ -0,0 +1,35 @@ +/* + usbip.h + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr 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. + + simavr 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 simavr. If not, see . +*/ + + +struct usbip_t; + +struct usbip_t * +usbip_create( + struct avr_t * avr); + +void +usbip_destroy( + struct usbip_t *); + +void * +usbip_main( + void * /* struct usbip_t * */); diff --git a/examples/parts/usbip_tester.py b/examples/parts/usbip_tester.py new file mode 100755 index 000000000..9c7204022 --- /dev/null +++ b/examples/parts/usbip_tester.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +# +# This is a quickly thrown together emulation of the kernel + usbip utilities +# side of the usbip protocol +# +# It will connect to the default usbip port on localhost, enumerate and +# configure the device, and run though some cdc commands. +# +# It's used as a developing aid for parts/usbip.c + +from collections import namedtuple +from contextlib import closing +import socket +import struct +import binascii +import unittest +import time + +Common_s = struct.Struct("!HHI") +Common = namedtuple("Common", "version code status") +USBIP_OP_IMPORT = 0x03 +USBIP_VER = 0x0106 +USBIP_SYSFS_BUS_ID_SIZE = 32 +USBIP_SYSFS_PATH_MAX = 256 +USBIP_CMD_SUBMIT = 0x0001 + +class USBNak(Exception): + pass + +class USBIPError(Exception): + pass + +def setuppkt(typ, req, val, idx, ln=None, dta=None): + if ln is None and dta is not None: + return struct.pack("BBHHH", typ, req, val, idx, len(dta)) + dta + else: + return struct.pack("BBHHH", typ, req, val, idx, ln) + +def usbip_submit_out(s, setuppkt=None, ep=0, dta = b""): + direction = 0 + seqno = 1 + if setuppkt is None: + setuppkt = b"\0\0\0\0\0\0\0\0" + elif len(setuppkt) > 8: + dta = setuppkt[8:] + setuppkt = setuppkt[:8] + + s.send(struct.pack("!IIIIIIiiii", + USBIP_CMD_SUBMIT, seqno, 0x10002, direction, ep, + 0x200, len(dta), 0, 0, 0) + setuppkt + dta + ) + X = struct.Struct("!IIIIIIiiiixxxxxxxx") + x = X.unpack(s.recv(X.size)) + if x[0] != 3: + raise USBIPError("Response is not sumbmit return") + if x[1] != 1: + raise USBIPError("Sequence number wrong") +## if x[2] != 0: +## raise USBIPError("Device id wrong") +## if x[3] != 0: +## raise USBIPError("Direction bit is wrong") +## if x[4] != ep: +## raise USBIPError("Endpoint# is wrong") + if x[6] != 0: + raise USBIPError("Unexpected non-zero buffer length") + if x[5] != 0: + raise USBNak() + +def usbip_submit_in(s, setuppkt=None, ep=0, maxsz=0): + direction = 1 + seqno = 1 + if setuppkt is None: + setuppkt = b"\0\0\0\0\0\0\0\0" + elif maxsz == 0: + maxsz = struct.unpack_from("H", setuppkt, 6)[0] + print("infer maxsz: ",maxsz) + s.send(struct.pack("!IIIIIIiiii", + USBIP_CMD_SUBMIT, seqno, 0x10002, direction, ep, + 0x200, maxsz, 0, 0, 0) + setuppkt + ) + + X = struct.Struct("!IIIIIIiiiixxxxxxxx") + x = X.unpack(s.recv(X.size)) + if x[0] != 3: + raise USBIPError("Response is not sumbmit return") + if x[1] != 1: + raise USBIPError("Sequence number wrong") +## if x[2] != 0: +## raise USBIPError("Device id wrong") +## if x[3] != 0: +## raise USBIPError("Direction bit is wrong") +## if x[4] != 0: +## raise USBIPError("Endpoint# is wrong") + if x[5] != 0: + raise USBNak() + return s.recv(x[6]) + + +class TestStuff(unittest.TestCase): + def usbip_attach(self, s): + s.send(struct.pack("!HHxxxx32s", USBIP_VER, USBIP_OP_IMPORT | 0x8000, b"1-1")) + X = struct.Struct("!HHI") + x = X.unpack(s.recv(X.size)) + self.assertEqual(x[0], USBIP_VER) + self.assertEqual(x[1], USBIP_OP_IMPORT) + self.assertEqual(x[2], 0, "status ok import-op") + + + X = struct.Struct("!%ds%dsIIIHHHBBBBBB"%(USBIP_SYSFS_PATH_MAX, USBIP_SYSFS_BUS_ID_SIZE)) + x = X.unpack(s.recv(X.size)) + x = (x[0].strip(b'\0'), x[1].strip(b'\0'), x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10],x[11],x[12],x[13],) + print("attached {} {}\n {} {} {}\n {:x} {:x} {:x}\n {} {} {}\n {} {} {}".format(*x)) + + + def get_device_desc(self, s): + print("get device desc") + dta = usbip_submit_in(s, setuppkt(0x80, 6, 0x100, 0, 64)) + self.assertEqual(dta, b'\x12\x01\x00\x02\x02\x00\x00\x10\xc0\x16\x7a\x04\x00\x01\x01\x02\x03\x01') + + + def get_device_qualifier(self, s): + print("get device qualifier") + + with self.assertRaises(USBNak): + usbip_submit_in(s, setuppkt(0x80, 6, 0x600, 0, 10)) + + + def get_config_descriptor(self, s): + print("get config1") + + + dta = usbip_submit_in(s, setuppkt(0x80, 6, 0x200, 0, 9)) + self.assertEqual(dta, b'\t\x02C\x00\x02\x01\x00\xc02') + + config_size = struct.unpack_from("H", dta, 2)[0] + self.assertEqual(config_size, 67) + + print("get config2") + dta = usbip_submit_in(s, setuppkt(0x80, 6, 0x200, 0, config_size)) + data = b'\x09\x02\x43\x00\x02\x01\x00\xc0\x32\x09\x04\x00\x00\x01\x02\x02\x01\x00\x05\x24\x00\x10\x01\x05\x24\x01\x01\x01\x04\x24\x02\x06\x05\x24\x06\x00\x01\x07\x05\x82\x03\x10\x00\x40\x09\x04\x01\x00\x02\x0a\x00\x00\x00\x07\x05\x03\x02\x20\x00\x00\x07\x05\x84\x02 \x00\x00' + self.assertEqual(dta, data) + + def get_strings(self, s): + print("get language code") + self.assertEqual( + usbip_submit_in(s, setuppkt(0x80, 6, 0x300, 0, 255)), + b'\x04\x03\t\x04') + + print("get name1") + self.assertEqual( + usbip_submit_in(s, setuppkt(0x80, 6, 0x302, 0x409, 255)), + b'\x16\x03U\x00S\x00B\x00 \x00S\x00e\x00r\x00i\x00a\x00l\x00') + + print("get manuf") + self.assertEqual( + usbip_submit_in(s, setuppkt(0x80, 6, 0x301, 0x409, 255)), + b'\x14\x03Y\x00o\x00u\x00r\x00 \x00N\x00a\x00m\x00e\x00') + + + print("get serial") + self.assertEqual( + usbip_submit_in(s, setuppkt(0x80, 6, 0x303, 0x409, 255)), + b'\x0c\x031\x002\x003\x004\x005\x00') + + + def set_config(self, s): + usbip_submit_out(s, setuppkt(0x00, 9, 0x01, 0, 0)) + + def set_line_coding(self, s): + print("send cdc ctrl 1") + usbip_submit_out(s, setuppkt(0x21, 0x20, 0x00, 0, dta=b'\x80\x25\x00\x00\x00\x00\x08')) + + print("send cdc ctrl 2") + usbip_submit_out(s, setuppkt(0x21, 0x20, 0x00, 0, dta=b'\x00\xe1\x00\x00\x00\x00\x08')) + + # sleep some + + print("send cdc ctrl 3") + usbip_submit_out(s, setuppkt(0x21, 0x22, 0x03, 0, 0)) + + + def poll_int_ep(self, s): + print("poll_int") + + with self.assertRaises(USBNak): + usbip_submit_in(s, ep=2, maxsz=64) + + + def write_bulk(self, s, dta=b"H", ep=3): + print("write_bulk") + max_retry = 2 + for retry in range(max_retry + 1): + try: + usbip_submit_out(s, ep=ep, dta=dta) + except USBNak: + if retry < max_retry: + time.sleep(0.05) + continue + else: + raise + break + + def read_bulk(self, s, ep=4, expectNak=False): + print("read_bulk") + max_retry = 12 + for retry in range(max_retry + 1): + + if expectNak: + with self.assertRaises(USBNak): + usbip_submit_in(s, ep=ep, maxsz=64) + else: + try: + dta = usbip_submit_in(s, ep=ep, maxsz=64) + if dta == b'': + raise USBNak + except USBNak: + if retry < max_retry: + time.sleep(0.05) + continue + else: + self.assertTrue(False, "expected data but none arrived") + self.assertEqual(dta, b'H') + break + + def xtest1(self): + with socket.create_connection(("localhost", 3240)) as s: + + self.usbip_attach(s) + + self.get_device_desc(s) + + self.get_device_qualifier(s) + + self.get_config_descriptor(s) + + self.get_strings(s) + + self.set_config(s) + + time.sleep(0.1) + + self.set_line_coding(s) + + for x in range(10): + self.poll_int_ep(s) + + for x in range(10): + self.write_bulk(s) + self.read_bulk(s) + + + + + def test1(self): +# for i in range(10): +# print("="*20,"iteration",i,"="*20) + self.xtest1() + + +if __name__ =="__main__": + unittest.main() diff --git a/examples/parts/usbip_types.h b/examples/parts/usbip_types.h new file mode 100644 index 000000000..e1c92cbd2 --- /dev/null +++ b/examples/parts/usbip_types.h @@ -0,0 +1,150 @@ +//ref https://github.com/torvalds/linux/blob/master/tools/usb/usbip +//ref https://github.com/torvalds/linux/blob/master/drivers/usb/usbip + +#define USBIP_SYSFS_PATH_MAX 256 +#define USBIP_SYSFS_BUS_ID_SIZE 32 + +struct usbip_usb_interface { + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t padding; /* alignment */ +} __attribute__((packed)); + +struct usbip_usb_device { + char path[USBIP_SYSFS_PATH_MAX]; + char busid[USBIP_SYSFS_BUS_ID_SIZE]; + + uint32_t busnum; + uint32_t devnum; + uint32_t speed; + + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bConfigurationValue; + uint8_t bNumConfigurations; + uint8_t bNumInterfaces; +} __attribute__((packed)); + + +#define USBIP_PROTO_VERSION ((1<<8) | 6) +struct usbip_op_common { + uint16_t version; + +#define USBIP_OP_REQUEST (0x80 << 8) +#define USBIP_OP_REPLY (0x00 << 8) + uint16_t code; + +#define USBIP_ST_OK 0x00 +#define USBIP_ST_NA 0x01 + uint32_t status; + +} __attribute__((packed)); + +#define USBIP_OP_DEVLIST 0x05 + +struct usbip_op_devlist_request { +} __attribute__((packed)); + +struct usbip_op_devlist_reply { + uint32_t ndev; + /* followed by reply_extra[] */ +} __attribute__((packed)); + +struct usbip_op_devlist_reply_extra { + struct usbip_usb_device udev; + struct usbip_usb_interface uinf[]; +} __attribute__((packed)); + + +#define USBIP_OP_IMPORT 0x03 +struct usbip_op_import_request { + char busid[USBIP_SYSFS_BUS_ID_SIZE]; +} __attribute__((packed)); + +struct usbip_op_import_reply { + struct usbip_usb_device udev; +// struct usbip_usb_interface uinf[]; +} __attribute__((packed)); + +struct usbip_common_hdr { + uint32_t command; + uint32_t seqnum; + uint32_t devid; // (busnum << 16) | devnum + uint32_t direction; + uint32_t ep; +} __attribute__ ((__packed__)); + +#define USBIP_CMD_SUBMIT 0x0001 +#define USBIP_CMD_UNLINK 0x0002 +#define USBIP_RET_SUBMIT 0x0003 +#define USBIP_RET_UNLINK 0x0004 +#define USBIP_DIR_OUT 0x00 +#define USBIP_DIR_IN 0x01 + + +struct usbip_cmd_submit { + uint32_t transfer_flags; + int32_t transfer_buffer_length; + int32_t start_frame; + int32_t number_of_packets; + int32_t interval; + unsigned char setup[8]; +} __attribute__ ((__packed__)); + +/* ++ Allowed transfer_flags | value | control | interrupt | bulk | isochronous ++ -------------------------+------------+---------+-----------+----------+------------- ++ URB_SHORT_NOT_OK | 0x00000001 | only in | only in | only in | no ++ URB_ISO_ASAP | 0x00000002 | no | no | no | yes ++ URB_NO_TRANSFER_DMA_MAP | 0x00000004 | yes | yes | yes | yes ++ URB_NO_FSBR | 0x00000020 | yes | no | no | no ++ URB_ZERO_PACKET | 0x00000040 | no | no | only out | no ++ URB_NO_INTERRUPT | 0x00000080 | yes | yes | yes | yes ++ URB_FREE_BUFFER | 0x00000100 | yes | yes | yes | yes ++ URB_DIR_MASK | 0x00000200 | yes | yes | yes | yes +*/ + +struct usbip_ret_submit { + int32_t status; + int32_t actual_length; + int32_t start_frame; + int32_t number_of_packets; + int32_t error_count; + long long setup; +} __attribute__ ((__packed__)); + + +struct usbip_cmd_unlink { + int32_t seqnum_urb; + int32_t pad1; + int32_t pad2; + int32_t pad3; + int32_t pad4; + long long pad5; +} __attribute__ ((__packed__)); + + +struct usbip_ret_unlink { + int32_t status; + int32_t pad1; + int32_t pad2; + int32_t pad3; + int32_t pad4; + long long pad5; +} __attribute__ ((__packed__)); + +struct usbip_header { + struct usbip_common_hdr hdr; + union { + struct usbip_cmd_submit submit; + struct usbip_ret_submit retsubmit; + struct usbip_cmd_unlink unlink; + struct usbip_ret_unlink retunlink; + } u; +} __attribute__ ((__packed__)); From ba4a731868d4c015969743f385d3e991baad8ae1 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 13:37:05 +0200 Subject: [PATCH 2/9] examples/extra_board_usb: switch to usbip --- examples/extra_board_usb/Makefile | 24 ++++++------------------ examples/extra_board_usb/simusb.c | 23 ++++++++++++++--------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/examples/extra_board_usb/Makefile b/examples/extra_board_usb/Makefile index f7f668eb9..647b8ee78 100644 --- a/examples/extra_board_usb/Makefile +++ b/examples/extra_board_usb/Makefile @@ -19,12 +19,11 @@ target= simusb firm_src = at90usb162_cdc_loopback.c firmware = ${firm_src:.c=.hex} +firmware2 = ${firm_src:.c=.axf} simavr = ../../ IPATH = . IPATH += ../parts -IPATH += ../vhci/include -IPATH += ../vhci IPATH += ${simavr}/include IPATH += ${simavr}/simavr/sim #IPATH += /usr/local/include @@ -32,30 +31,19 @@ IPATH += ${simavr}/simavr/sim VPATH = . VPATH += ../parts -LDFLAGS += -lpthread -lusb_vhci -L../vhci/lib +LDFLAGS += -lpthread -all: obj ${firmware} ${target} +all: obj ${firmware} ${target} ${firmware2} include ${simavr}/Makefile.common board = ${OBJ}/${target}.elf -${board} : ${OBJ}/vhci_usb.o +${board} : ${OBJ}/usbip.o ${board} : ${OBJ}/${target}.o -../vhci/lib/libusb_vhci.a: - @echo -n "BUILDIN $@ " - @{ export CC=;export CFLAGS=; $(MAKE) -j -C ../vhci >/tmp/vhci.build.log 2>&1 || \ - { echo "ERROR check /tmp/vhci.build.log"; exit 1; }; } && \ - echo " Done" - -vhci : ../vhci/lib/libusb_vhci.a - -clean-vhci: - $(MAKE) -C ../vhci clean - -${target}: vhci ${board} +${target}: ${board} @echo $@ done -clean: clean-${OBJ} clean-vhci +clean: clean-${OBJ} rm -rf *.a *.axf *.hex ${target} *.vcd diff --git a/examples/extra_board_usb/simusb.c b/examples/extra_board_usb/simusb.c index 7332f453b..191d288b6 100644 --- a/examples/extra_board_usb/simusb.c +++ b/examples/extra_board_usb/simusb.c @@ -35,10 +35,10 @@ #include "sim_elf.h" #include "sim_hex.h" #include "sim_gdb.h" -#include "vhci_usb.h" +#include "usbip.h" #include "sim_vcd_file.h" -struct vhci_usb_t vhci_usb; +struct usbip_t * usbip; avr_t * avr = NULL; avr_vcd_t vcd_file; @@ -58,7 +58,7 @@ void avr_special_init( avr_t* avr, void *data) if(avr->flash) free(avr->flash); // open the file flash_data->avr_flash_fd = open(flash_data->avr_flash_path, - O_RDWR|O_CREAT, 0644); + O_RDWR|O_CREAT, 0644); if (flash_data->avr_flash_fd < 0) { perror(flash_data->avr_flash_path); exit(1); @@ -66,7 +66,7 @@ void avr_special_init( avr_t* avr, void *data) // resize and map the file the file (void)ftruncate(flash_data->avr_flash_fd, avr->flashend + 1); avr->flash = (uint8_t*)mmap(NULL, avr->flashend + 1, // 32k is multiple of 4096 - PROT_READ|PROT_WRITE, MAP_SHARED, flash_data->avr_flash_fd, 0); + PROT_READ|PROT_WRITE, MAP_SHARED, flash_data->avr_flash_fd, 0); if (!avr->flash) { fprintf(stderr, "unable to map memory\n"); perror(flash_data->avr_flash_path); @@ -89,7 +89,6 @@ void avr_special_deinit( avr_t* avr, void *data) int main(int argc, char *argv[]) { -// elf_firmware_t f; const char * pwd = dirname(argv[0]); struct avr_flash flash_data; @@ -98,7 +97,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "%s: Error creating the AVR core\n", argv[0]); exit(1); } - strcpy(flash_data.avr_flash_path, "simusb_flash.bin"); + strcpy(flash_data.avr_flash_path, "simusb_flash.bin"); flash_data.avr_flash_fd = 0; // register our own functions avr->custom.init = avr_special_init; @@ -131,16 +130,22 @@ int main(int argc, char *argv[]) // even if not setup at startup, activate gdb if crashing avr->gdb_port = 1234; + avr_gdb_init(avr); if (0) { //avr->state = cpu_Stopped; avr_gdb_init(avr); } - vhci_usb_init(avr, &vhci_usb); - vhci_usb_connect(&vhci_usb, '0'); - + usbip = usbip_create(avr); + if (!usbip) { + fprintf(stderr, "usbip_create failed\n"); + exit(1); + } + pthread_t usb_thread; + pthread_create(&usb_thread, NULL, usbip_main, usbip); while (1) { avr_run(avr); } + usbip_destroy(usbip); } From 71efa7e84ef37e7495e7dd91bf3307a9f4f7928c Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 13:42:47 +0200 Subject: [PATCH 3/9] sim/avr_usb: move types to separate file --- simavr/sim/avr_usb.c | 120 +------------------------------------ simavr/sim/avr_usb_int.h | 124 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 119 deletions(-) create mode 100644 simavr/sim/avr_usb_int.h diff --git a/simavr/sim/avr_usb.c b/simavr/sim/avr_usb.c index d87aca5ea..13d1aca88 100644 --- a/simavr/sim/avr_usb.c +++ b/simavr/sim/avr_usb.c @@ -32,126 +32,11 @@ #include #include #include "avr_usb.h" +#include "avr_usb_int.h" -enum usb_regs -{ - usbcon = 0, - udcon = 8, - udint = 9, - udien = 10, - udaddr = 11, - udfnuml = 12, - udfnumh = 13, - udmfn = 14, -// _res=15, - ueintx = 16, - uenum = 17, - uerst = 18, - ueconx = 19, - uecfg0x = 20, - uecfg1x = 21, - uesta0x = 22, - uesta1x = 23, - ueienx = 24, - uedatx = 25, - uebclx = 26, -// _res2=27, - ueint = 28, - otgtcon = 29, -}; -union _ueintx { - struct { - uint8_t txini :1; - uint8_t stalledi :1; - uint8_t rxouti :1; - uint8_t rxstpi :1; - uint8_t nakouti :1; - uint8_t rwal :1; - uint8_t nakini :1; - uint8_t fifocon :1; - }; - uint8_t v; -}; -struct _epstate { - union _ueintx ueintx; - uint8_t dummy1; - uint8_t dummy2; - union { - struct { - uint8_t epen :1; - uint8_t res :2; - uint8_t rstdt :1; - uint8_t stallrqc :1; - uint8_t stallrq :1; - }; - uint8_t v; - } ueconx; - union { - struct { - uint8_t epdir :1; - uint8_t res :5; - uint8_t eptype :2; - }; - uint8_t v; - } uecfg0x; - union { - struct { - uint8_t res :1; - uint8_t alloc :1; - uint8_t epbk1 :2; - uint8_t epsize :3; - uint8_t res2 :1; - }; - uint8_t v; - } uecfg1x; - union { - struct { - uint8_t nbusybk :2; - uint8_t dtseq :2; - uint8_t res :1; - uint8_t underfi :1; - uint8_t overfi :1; - uint8_t cfgok :1; - }; - uint8_t v; - } uesta0x; - union { - struct { - uint8_t curbk :2; - uint8_t ctrldir :1; - uint8_t res :5; - }; - uint8_t v; - } uesta1x; - union { - struct { - uint8_t txine :1; - uint8_t stallede :1; - uint8_t rxoute :1; - uint8_t rxstpe :1; - uint8_t nakoute :1; - uint8_t res :1; - uint8_t nakine :1; - uint8_t flerre :1; - }; - uint8_t v; - } ueienx; - - struct { - uint8_t bytes[64]; - uint8_t tail; - } bank[2]; - uint8_t current_bank; - int setup_is_read; -}; -struct usb_internal_state { - struct _epstate ep_state[5]; - avr_int_vector_t com_vect; - avr_int_vector_t gen_vect; -}; const uint8_t num_endpoints = 5;//sizeof (struct usb_internal_state.ep_state) / sizeof (struct usb_internal_state.ep_state[0]); @@ -223,9 +108,6 @@ raise_ep_interrupt( } } -enum usbints { - suspi = 0, sofi = 2, eorsti = 3, wakeupi = 4, eorsmi = 5, uprsmi = 6 -}; static void raise_usb_interrupt( avr_usb_t * p, diff --git a/simavr/sim/avr_usb_int.h b/simavr/sim/avr_usb_int.h new file mode 100644 index 000000000..dabb8bd09 --- /dev/null +++ b/simavr/sim/avr_usb_int.h @@ -0,0 +1,124 @@ +enum usb_regs +{ + usbcon = 0, + udcon = 8, + udint = 9, + udien = 10, + udaddr = 11, + udfnuml = 12, + udfnumh = 13, + udmfn = 14, +// _res=15, + ueintx = 16, + uenum = 17, + uerst = 18, + ueconx = 19, + uecfg0x = 20, + uecfg1x = 21, + uesta0x = 22, + uesta1x = 23, + ueienx = 24, + uedatx = 25, + uebclx = 26, +// _res2=27, + ueint = 28, + otgtcon = 29, +}; + +union _ueintx { + struct { + uint8_t txini :1; + uint8_t stalledi :1; + uint8_t rxouti :1; + uint8_t rxstpi :1; + uint8_t nakouti :1; + uint8_t rwal :1; + uint8_t nakini :1; + uint8_t fifocon :1; + }; + uint8_t v; +}; + +struct _epstate { + union _ueintx ueintx; + uint8_t dummy1; + uint8_t dummy2; + union { + struct { + uint8_t epen :1; + uint8_t res :2; + uint8_t rstdt :1; + uint8_t stallrqc :1; + uint8_t stallrq :1; + }; + uint8_t v; + } ueconx; + union { + struct { + uint8_t epdir :1; + uint8_t res :5; + uint8_t eptype :2; + }; + uint8_t v; + } uecfg0x; + union { + struct { + uint8_t res :1; + uint8_t alloc :1; + uint8_t epbk1 :2; + uint8_t epsize :3; + uint8_t res2 :1; + }; + uint8_t v; + } uecfg1x; + union { + struct { + uint8_t nbusybk :2; + uint8_t dtseq :2; + uint8_t res :1; + uint8_t underfi :1; + uint8_t overfi :1; + uint8_t cfgok :1; + }; + uint8_t v; + } uesta0x; + union { + struct { + uint8_t curbk :2; + uint8_t ctrldir :1; + uint8_t res :5; + }; + uint8_t v; + } uesta1x; + union { + struct { + uint8_t txine :1; + uint8_t stallede :1; + uint8_t rxoute :1; + uint8_t rxstpe :1; + uint8_t nakoute :1; + uint8_t res :1; + uint8_t nakine :1; + uint8_t flerre :1; + }; + uint8_t v; + } ueienx; + + struct { + uint8_t bytes[64]; + uint8_t tail; + } bank[2]; + uint8_t current_bank; +}; + +struct usb_internal_state { + pthread_mutex_t mutex; + pthread_cond_t cpu_action; + struct _epstate ep_state[5]; + avr_int_vector_t com_vect; + avr_int_vector_t gen_vect; +}; + +enum usbints { + suspi = 0, sofi = 2, eorsti = 3, wakeupi = 4, eorsmi = 5, uprsmi = 6 +}; From 6aa968d14cc878e81a58a5347f90ad0b36fbe6f2 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 15:10:29 +0200 Subject: [PATCH 4/9] sim/avr_usb: whitespace / code conformance --- simavr/sim/avr_usb.c | 80 ++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/simavr/sim/avr_usb.c b/simavr/sim/avr_usb.c index 13d1aca88..6c3b65b68 100644 --- a/simavr/sim/avr_usb.c +++ b/simavr/sim/avr_usb.c @@ -235,9 +235,9 @@ ep_fifo_usb_read( static int ep_fifo_usb_write( - struct _epstate * epstate, - uint8_t * buf, - uint8_t len) + struct _epstate * epstate, + uint8_t * buf, + size_t len) { if (!epstate->ueconx.epen) { printf("WARNING! Adding bytes to non configured endpoint\n"); @@ -262,9 +262,9 @@ ep_fifo_usb_write( static uint8_t avr_usb_ep_read_bytecount( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + void * param) { avr_usb_t * p = (avr_usb_t *) param; return ep_fifo_count(get_epstate(p, current_ep_to_cpu(p))); @@ -283,7 +283,11 @@ avr_usb_udaddr_write( } static void -avr_usb_udcon_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) +avr_usb_udcon_write( + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param) { avr_usb_t * p = (avr_usb_t *)param; @@ -294,10 +298,10 @@ avr_usb_udcon_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * pa static void avr_usb_uenum_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param) { assert(v < num_endpoints); avr_core_watch_write(avr, addr, v); @@ -322,10 +326,10 @@ avr_usb_ep_read_ueintx( static void avr_usb_ep_write_ueintx( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param) { avr_usb_t * p = (avr_usb_t *) param; uint8_t ep = current_ep_to_cpu(p); @@ -359,9 +363,9 @@ avr_usb_ep_write_ueintx( static uint8_t avr_usb_ep_read( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + void * param) { avr_usb_t * p = (avr_usb_t *) param; uint8_t laddr = addr - p->r_usbcon; @@ -382,10 +386,10 @@ avr_usb_ep_read( static void avr_usb_ep_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param) { avr_usb_t * p = (avr_usb_t *) param; struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); @@ -431,9 +435,9 @@ avr_usb_ep_write( static uint8_t avr_usb_ep_read_data( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + void * param) { avr_usb_t * p = (avr_usb_t *) param; int ret = ep_fifo_cpu_readbyte(get_epstate(p, current_ep_to_cpu(p))); @@ -448,10 +452,10 @@ avr_usb_ep_read_data( static void avr_usb_ep_write_data( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param) { avr_usb_t * p = (avr_usb_t *) param; int ret = ep_fifo_cpu_writebyte(get_epstate(p, current_ep_to_cpu(p)), v); @@ -464,10 +468,10 @@ avr_usb_ep_write_data( static void avr_usb_pll_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param) { v |= (v >> 1) & 1; avr_core_watch_write(avr, addr, v); @@ -476,9 +480,9 @@ avr_usb_pll_write( avr_cycle_count_t sof_generator( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) + struct avr_t * avr, + avr_cycle_count_t when, + void * param) { avr_usb_t * p = (avr_usb_t *) param; //stop sof generation if detached @@ -648,7 +652,9 @@ register_vectors( avr_register_vector(avr, &p->state->gen_vect); } -void avr_usb_init(avr_t * avr, avr_usb_t * p) +void avr_usb_init( + avr_t * avr, + avr_usb_t * p) { p->io = _io; From 76e0410a1ddc300c166f79577fb10033ffbbfd12 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 15:12:04 +0200 Subject: [PATCH 5/9] sim/avr_usb: generate sof interrupt --- simavr/sim/avr_usb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/simavr/sim/avr_usb.c b/simavr/sim/avr_usb.c index 6c3b65b68..93761ea4f 100644 --- a/simavr/sim/avr_usb.c +++ b/simavr/sim/avr_usb.c @@ -20,7 +20,6 @@ */ /* TODO correct reset values */ -/* TODO generate sofi every 1ms (when connected) */ /* TODO otg support? */ /* TODO drop bitfields? */ /* TODO thread safe ioctls */ @@ -490,7 +489,7 @@ sof_generator( return 0; else { raise_usb_interrupt(p, sofi); - return when; + return when+1000; } } @@ -573,8 +572,7 @@ avr_usb_ioctl( AVR_LOG(io->avr, LOG_TRACE, "USB: __USB_RESET__\n"); reset_endpoints(io->avr, p); raise_usb_interrupt(p, eorsti); - if (0) - avr_cycle_timer_register_usec(io->avr, 1000, sof_generator, p); + avr_cycle_timer_register_usec(io->avr, 1000, sof_generator, p); return 0; default: return -1; From 86105c364558d8cbc4aaa6541e0d8c7863c9a0a5 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 13:59:55 +0200 Subject: [PATCH 6/9] sim/avr_usb: thread safetiness & code cleanup --- Makefile.common | 2 +- simavr/sim/avr_usb.c | 403 ++++++++++++++++++++++++++----------------- 2 files changed, 248 insertions(+), 157 deletions(-) diff --git a/Makefile.common b/Makefile.common index 9b56e2760..c538b3bbb 100644 --- a/Makefile.common +++ b/Makefile.common @@ -112,7 +112,7 @@ SHELL := ${shell which bash} OBJ := obj-${shell $(CC) -dumpmachine} LIBDIR := ${shell pwd}/${SIMAVR}/${OBJ} -LDFLAGS += -L${LIBDIR} -lsimavr -lm +LDFLAGS += -L${LIBDIR} -lsimavr -lm -lpthread LDFLAGS += -lelf diff --git a/simavr/sim/avr_usb.c b/simavr/sim/avr_usb.c index 93761ea4f..b69ecb3c2 100644 --- a/simavr/sim/avr_usb.c +++ b/simavr/sim/avr_usb.c @@ -22,7 +22,6 @@ /* TODO correct reset values */ /* TODO otg support? */ /* TODO drop bitfields? */ -/* TODO thread safe ioctls */ /* TODO dual-bank endpoint buffers */ /* TODO actually pay attention to endpoint memory allocation ? buggy endpoint configuration doesn't matter in the simulator now. */ @@ -30,12 +29,24 @@ #include #include #include +#include #include "avr_usb.h" #include "avr_usb_int.h" +#define min(a,b) ((a)<(b)?(a):(b)) +static inline struct timespec ts_add( + struct timespec a, + struct timespec b) +{ + a.tv_sec += b.tv_sec; + a.tv_nsec += b.tv_nsec; + if (a.tv_nsec >= 1000000000L) { + a.tv_sec++ ; a.tv_nsec = a.tv_nsec - 1000000000L; + } - + return a; +} const uint8_t num_endpoints = 5;//sizeof (struct usb_internal_state.ep_state) / sizeof (struct usb_internal_state.ep_state[0]); @@ -75,7 +86,6 @@ raise_ep_interrupt( enum epints irq) { struct _epstate * epstate = get_epstate(p, ep); - assert(ep < num_endpoints); avr->data[p->r_usbcon + ueint] |= 1 << ep; switch (irq) { case txini: @@ -172,47 +182,10 @@ ep_fifo_count( } static int -ep_fifo_cpu_readbyte( - struct _epstate * epstate) -{ - uint8_t i, j; - uint8_t v = epstate->bank[epstate->current_bank].bytes[0]; - - if (!epstate->ueconx.epen) { - printf("WARNING! Adding bytes to non configured endpoint\n"); - return -1; - } - - if (ep_fifo_empty(epstate)) - return -2; - - for (i = 0, j = ep_fifo_count(epstate) - 1; i < j; i++) - epstate->bank[epstate->current_bank].bytes[i] = - epstate->bank[epstate->current_bank].bytes[i + 1]; - epstate->bank[epstate->current_bank].tail--; - return v; -} - -static int -ep_fifo_cpu_writebyte( +host_read_ep_fifo( struct _epstate * epstate, - uint8_t v) -{ - if (!epstate->ueconx.epen) { - printf("WARNING! Adding bytes to non configured endpoint\n"); - return -1; - } - if (ep_fifo_full(epstate)) - return -2; - - epstate->bank[epstate->current_bank].bytes[epstate->bank[epstate->current_bank].tail++] = v; - return 0; -} - -static int -ep_fifo_usb_read( - struct _epstate * epstate, - uint8_t * buf) + uint8_t * buf, + size_t sz) { if (!epstate->ueconx.epen) { printf("WARNING! Reading from non configured endpoint\n"); @@ -225,15 +198,18 @@ ep_fifo_usb_read( return AVR_IOCTL_USB_NAK; } - int ret = epstate->bank[epstate->current_bank].tail; + if (sz < epstate->bank[epstate->current_bank].tail) + printf("WARNING! Loosing bytes in %s\n", __FUNCTION__); + + int ret = min(epstate->bank[epstate->current_bank].tail, sz); memcpy(buf, epstate->bank[epstate->current_bank].bytes, - epstate->bank[epstate->current_bank].tail); + ret); epstate->bank[epstate->current_bank].tail = 0; - return ret; + return ret + (ret < ep_fifo_size(epstate) ? 0x100 : 0); } static int -ep_fifo_usb_write( +host_write_ep_fifo( struct _epstate * epstate, uint8_t * buf, size_t len) @@ -250,13 +226,13 @@ ep_fifo_usb_write( return AVR_IOCTL_USB_NAK; } - if (len > ep_fifo_size(epstate)) { - printf("EP OVERFI\n"); - len = sizeof epstate->bank[epstate->current_bank].bytes; - }memcpy(epstate->bank[epstate->current_bank].bytes, buf, len); + len = min(ep_fifo_size(epstate), len); + + memcpy(epstate->bank[epstate->current_bank].bytes, buf, len); epstate->bank[epstate->current_bank].tail = len; + epstate->ueintx.rwal = 1 & (epstate->uecfg0x.eptype != 0); - return 0; + return len; } static uint8_t @@ -266,7 +242,11 @@ avr_usb_ep_read_bytecount( void * param) { avr_usb_t * p = (avr_usb_t *) param; - return ep_fifo_count(get_epstate(p, current_ep_to_cpu(p))); + if (pthread_mutex_lock(&p->state->mutex)) + abort(); + uint8_t ret = ep_fifo_count(get_epstate(p, current_ep_to_cpu(p))); + pthread_mutex_unlock(&p->state->mutex); + return ret; } static void @@ -306,22 +286,7 @@ avr_usb_uenum_write( avr_core_watch_write(avr, addr, v); } -static uint8_t -avr_usb_ep_read_ueintx( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - uint8_t ep = current_ep_to_cpu(p); - - if (p->state->ep_state[ep].uecfg0x.epdir) - p->state->ep_state[ep].ueintx.rwal = !ep_fifo_full(get_epstate(p, ep)); - else - p->state->ep_state[ep].ueintx.rwal = !ep_fifo_empty(get_epstate(p, ep)); - - return p->state->ep_state[ep].ueintx.v; -} +static int can_touch_txini = 1; static void avr_usb_ep_write_ueintx( @@ -332,18 +297,28 @@ avr_usb_ep_write_ueintx( { avr_usb_t * p = (avr_usb_t *) param; uint8_t ep = current_ep_to_cpu(p); + struct _epstate * epstate = get_epstate(p, ep); + int signalhost = 0; + + if(pthread_mutex_lock(&p->state->mutex)) + abort(); union _ueintx * newstate = (union _ueintx*) &v; - union _ueintx * curstate = &p->state->ep_state[ep].ueintx; + union _ueintx * curstate = &epstate->ueintx; if (curstate->rxouti & !newstate->rxouti) curstate->rxouti = 0; - if (curstate->txini & !newstate->txini) - curstate->txini = 0; + if (curstate->txini & !newstate->txini) { + if (can_touch_txini) { + curstate->txini = 0; + signalhost = 1; + } else + AVR_LOG(avr, LOG_WARNING, "USB: BUG, clearing txini in setup phase\n"); + } if (curstate->rxstpi & !newstate->rxstpi) { - curstate->txini = 1; - curstate->rxouti = 0; curstate->rxstpi = 0; + can_touch_txini = 1; + signalhost = 1; } if (curstate->fifocon & !newstate->fifocon) curstate->fifocon = 0; @@ -358,6 +333,10 @@ avr_usb_ep_write_ueintx( if ((curstate->v & 0xdf) == 0) avr->data[p->r_usbcon + ueint] &= 0xff ^ (1 << ep); // mark ep0 interrupt + + pthread_mutex_unlock(&p->state->mutex); + if (signalhost) + pthread_cond_signal(&p->state->cpu_action); } static uint8_t @@ -371,6 +350,8 @@ avr_usb_ep_read( uint8_t v; struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); + if (pthread_mutex_lock(&p->state->mutex)) + abort(); switch(laddr) { case ueconx: v = epstate->ueconx.v; break; case uecfg0x: v = epstate->uecfg0x.v; break; @@ -378,8 +359,10 @@ avr_usb_ep_read( case uesta0x: v = epstate->uesta0x.v; break; case uesta1x: v = epstate->uesta1x.v; break; case ueienx: v = epstate->ueienx.v; break; + case ueintx: v = epstate->ueintx.v; break; default:assert(0); } + pthread_mutex_unlock(&p->state->mutex); return v; } @@ -394,6 +377,9 @@ avr_usb_ep_write( struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); uint8_t laddr = addr - p->r_usbcon; + if (pthread_mutex_lock(&p->state->mutex)) + abort(); + switch (laddr) { case ueconx: if (v & 1 << 4) @@ -409,9 +395,11 @@ avr_usb_ep_write( case uecfg1x: epstate->uecfg1x.v = v; epstate->uesta0x.cfgok = epstate->uecfg1x.alloc; - if (epstate->uecfg0x.eptype == 0) + if (epstate->uecfg0x.eptype == 0) { epstate->ueintx.txini = 1; - else if (epstate->uecfg0x.epdir) { + epstate->ueintx.rwal = 0; + epstate->ueintx.fifocon = 0; + } else if (epstate->uecfg0x.epdir) { epstate->ueintx.txini = 1; epstate->ueintx.rwal = 1; epstate->ueintx.fifocon = 1; @@ -430,39 +418,66 @@ avr_usb_ep_write( default: assert(0); } + pthread_mutex_unlock(&p->state->mutex); } static uint8_t -avr_usb_ep_read_data( +avr_read_ep_fifo( struct avr_t * avr, avr_io_addr_t addr, void * param) { avr_usb_t * p = (avr_usb_t *) param; - int ret = ep_fifo_cpu_readbyte(get_epstate(p, current_ep_to_cpu(p))); + struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); + uint8_t ret = 0; - if (ret < 0) { - if (ret == -2) - raise_ep_interrupt(avr, p, current_ep_to_cpu(p), underfi); + if (!epstate->ueconx.epen) { + printf("WARNING! Reading bytes from non configured endpoint\n"); return 0; - } else - return (uint8_t) ret; + } + + if (ep_fifo_empty(epstate)) + raise_ep_interrupt(avr, p, current_ep_to_cpu(p), underfi); + else { + ret = epstate->bank[epstate->current_bank].bytes[0]; + + int i,j; + for (i = 0, j = ep_fifo_count(epstate) - 1; i < j; i++) + epstate->bank[epstate->current_bank].bytes[i] = + epstate->bank[epstate->current_bank].bytes[i + 1]; + epstate->bank[epstate->current_bank].tail--; + epstate->ueintx.rwal = !ep_fifo_empty(epstate); + } + return ret; } static void -avr_usb_ep_write_data( +avr_write_ep_fifo( struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) { avr_usb_t * p = (avr_usb_t *) param; - int ret = ep_fifo_cpu_writebyte(get_epstate(p, current_ep_to_cpu(p)), v); - if (ret == 0) + struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); + + if (!epstate->ueconx.epen) { + printf("WARNING! Adding bytes to non configured endpoint\n"); return; + } + + if (pthread_mutex_lock(&p->state->mutex)) + abort(); - if (ret == -2) + if (ep_fifo_full(epstate)) { + pthread_mutex_unlock(&p->state->mutex); raise_ep_interrupt(avr, p, current_ep_to_cpu(p), overfi); + } + else { + epstate->bank[epstate->current_bank].bytes[epstate->bank[epstate->current_bank].tail++] = v; + epstate->ueintx.rwal = !ep_fifo_full(epstate); + pthread_mutex_unlock(&p->state->mutex); + } } static void @@ -493,6 +508,135 @@ sof_generator( } } +static int +ioctl_usb_read( + avr_usb_t * p, + struct avr_io_usb * d) +{ + int ret; + struct timespec ts; + uint8_t ep = d->pipe & 0x7f; + struct _epstate * epstate = get_epstate(p, ep); + + if (epstate->ueconx.stallrq) { + raise_ep_interrupt(p->io.avr, p, 0, stalledi); + return AVR_IOCTL_USB_STALL; + } + if (ep && !epstate->uecfg0x.epdir) + AVR_LOG(p->io.avr, LOG_WARNING, "USB: Host reading from OUT endpoint?\n"); + + if (pthread_mutex_lock(&p->state->mutex)) + abort(); + + if (!d->sz && !d->buf && !epstate->ueintx.txini && !epstate->uecfg0x.eptype) { + // status already ok for control write + pthread_mutex_unlock(&p->state->mutex); + return 0; + } + + ret = 0; + clock_gettime(CLOCK_REALTIME, &ts); + if (ep) + ts = ts_add(ts, (struct timespec){0, 1000}); + else + ts = ts_add(ts, (struct timespec){0, 10000000L}); + while (epstate->ueintx.txini && !ret) + ret = pthread_cond_timedwait(&p->state->cpu_action, &p->state->mutex, &ts); + + ret = host_read_ep_fifo(epstate, d->buf, d->sz); + pthread_mutex_unlock(&p->state->mutex); + + if (ret >= 0) { + epstate->ueintx.fifocon = 1 & (epstate->uecfg0x.eptype != 0); + raise_ep_interrupt(p->io.avr, p, ep, txini); + + d->sz = ret; + ret = 0; + } + + return ret; +} + +static int +ioctl_usb_write( + avr_usb_t * p, + struct avr_io_usb * d) +{ + uint8_t ep = d->pipe & 0x7f; + struct _epstate * epstate = get_epstate(p, ep); + + if (ep && epstate->uecfg0x.epdir) + AVR_LOG(p->io.avr, LOG_WARNING, "USB: Host writing to IN endpoint?\n"); + + if (epstate->ueconx.stallrq) { + raise_ep_interrupt(p->io.avr, p, 0, stalledi); + return AVR_IOCTL_USB_STALL; + } + + if (pthread_mutex_lock(&p->state->mutex)) + abort(); + int ret = host_write_ep_fifo(epstate, d->buf, d->sz); + if (ret < 0) { + pthread_mutex_unlock(&p->state->mutex); + return ret; + } + d->sz = ret; + epstate->ueintx.fifocon = 1 & (epstate->uecfg0x.eptype != 0); + raise_ep_interrupt(p->io.avr, p, ep, rxouti); + pthread_mutex_unlock(&p->state->mutex); + return 0; +} + +static int +ioctl_usb_setup( + avr_usb_t * p, + struct avr_io_usb * d) +{ + int ret = 0; + struct timespec ts; + uint8_t ep = d->pipe & 0x7f; + struct _epstate * epstate = get_epstate(p, ep); + + if (pthread_mutex_lock(&p->state->mutex)) + abort(); + epstate->ueconx.stallrq = 0; + epstate->ueintx.rxouti = 0; + epstate->ueintx.txini = 1; + + assert(d->buf && d->sz==8); + + if (d->buf && d->sz) + ret = host_write_ep_fifo(epstate, d->buf, d->sz); + pthread_mutex_unlock(&p->state->mutex); + + if (ret < 0) + return ret; + + if (pthread_mutex_lock(&p->state->mutex)) + abort(); + + raise_ep_interrupt(p->io.avr, p, ep, rxstpi); + + // wait for cpu to ack setup + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; + ret = 0; + if (d->buf[0] & 0x80) { // control READ + while (!ret && (epstate->ueintx.rxstpi || epstate->ueintx.txini)) + ret = pthread_cond_timedwait(&p->state->cpu_action, &p->state->mutex, &ts); + epstate->ueintx.txini = 1; + } else { // control WRITE + // some implementations, like teensy clear everything on rxstp.. which is wrong + // for a ctrl-write.. aparently it's working on real hardware so we ignore txini + // changes until stp ack'ed. + can_touch_txini = 0; + while (!ret && (epstate->ueintx.rxstpi)) + ret = pthread_cond_timedwait(&p->state->cpu_action, &p->state->mutex, &ts); + } + pthread_mutex_unlock(&p->state->mutex); + return ret; +} + static int avr_usb_ioctl( struct avr_io_t * io, @@ -501,73 +645,11 @@ avr_usb_ioctl( { avr_usb_t * p = (avr_usb_t *) io; struct avr_io_usb * d = (struct avr_io_usb*) io_param; - struct _epstate * epstate = 0; - int ret; - uint8_t ep; switch (ctl) { - case AVR_IOCTL_USB_READ: - ep = d->pipe & 0x7f; - epstate = get_epstate(p, ep); - - if (epstate->ueconx.stallrq) { - raise_ep_interrupt(io->avr, p, 0, stalledi); - return AVR_IOCTL_USB_STALL; - } - if (ep && !epstate->uecfg0x.epdir) - AVR_LOG(io->avr, LOG_WARNING, "USB: Reading from IN endpoint from host??\n"); - - ret = ep_fifo_usb_read(epstate, d->buf); - if (ret < 0) { - // is this correct? It makes the cdc example work. - // Linux stops polling the data ep if we send naks,but - // according to usb spec nak'ing should be ok. - if (epstate->uecfg0x.eptype == 2) { - d->sz = 0; - return 0; - } else - return ret; - } - d->sz = ret; - ret = 0; - epstate->ueintx.fifocon = 1; - raise_ep_interrupt(io->avr, p, ep, txini); - return ret; - case AVR_IOCTL_USB_WRITE: - ep = d->pipe & 0x7f; - epstate = get_epstate(p, ep); - - if (ep && epstate->uecfg0x.epdir) - AVR_LOG(io->avr, LOG_WARNING, "USB: Writing to IN endpoint from host??\n"); - - if (epstate->ueconx.stallrq) { - raise_ep_interrupt(io->avr, p, 0, stalledi); - return AVR_IOCTL_USB_STALL; - } - - ret = ep_fifo_usb_write(epstate, d->buf, d->sz); - if (ret < 0) - return ret; - - epstate->ueintx.fifocon = 1; - raise_ep_interrupt(io->avr, p, ep, rxouti); - return 0; - case AVR_IOCTL_USB_SETUP: - ep = d->pipe & 0x7f; - epstate = get_epstate(p, ep); - - epstate->ueconx.stallrq = 0; - // teensy actually depends on this (fails to ack rxouti on usb - // control read status stage) even if the datasheet clearly states - // that one should do so. - epstate->ueintx.rxouti = 0; - - ret = ep_fifo_usb_write(epstate, d->buf, d->sz); - if (ret < 0) - return ret; - raise_ep_interrupt(io->avr, p, ep, rxstpi); - - return 0; + case AVR_IOCTL_USB_READ: return ioctl_usb_read(p, d); + case AVR_IOCTL_USB_WRITE: return ioctl_usb_write(p, d); + case AVR_IOCTL_USB_SETUP: return ioctl_usb_setup(p, d); case AVR_IOCTL_USB_RESET: AVR_LOG(io->avr, LOG_TRACE, "USB: __USB_RESET__\n"); reset_endpoints(io->avr, p); @@ -658,6 +740,16 @@ void avr_usb_init( p->state = calloc(1, sizeof *p->state); + pthread_mutexattr_t mutexattr; + pthread_mutexattr_init(&mutexattr); + pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK); + + if (pthread_mutex_init(&p->state->mutex, &mutexattr)) { + printf("FATAL: avr_usb mutex init failed\n"); + abort(); + } + pthread_mutexattr_destroy(&mutexattr); + avr_register_io(avr, &p->io); register_vectors(avr, p); // allocate this module's IRQ @@ -667,11 +759,11 @@ void avr_usb_init( avr_register_io_write(avr, p->r_usbcon + udcon, avr_usb_udcon_write, p); avr_register_io_write(avr, p->r_usbcon + uenum, avr_usb_uenum_write, p); - avr_register_io_read(avr, p->r_usbcon + uedatx, avr_usb_ep_read_data, p); - avr_register_io_write(avr, p->r_usbcon + uedatx, avr_usb_ep_write_data, p); + avr_register_io_read(avr, p->r_usbcon + uedatx, avr_read_ep_fifo, p); + avr_register_io_write(avr, p->r_usbcon + uedatx, avr_write_ep_fifo, p); avr_register_io_read(avr, p->r_usbcon + uebclx, avr_usb_ep_read_bytecount, p); //ro - avr_register_io_read(avr, p->r_usbcon + ueintx, avr_usb_ep_read_ueintx, p); + avr_register_io_read(avr, p->r_usbcon + ueintx, avr_usb_ep_read, p); avr_register_io_write(avr, p->r_usbcon + ueintx, avr_usb_ep_write_ueintx, p); register_io_ep_readwrite(avr, p, ueconx); @@ -683,4 +775,3 @@ void avr_usb_init( avr_register_io_write(avr, p->r_pllcsr, avr_usb_pll_write, p); } - From 4e97649edfda15097a24f80b48eb48c600740411 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 13:37:46 +0200 Subject: [PATCH 7/9] examples/board_usb: update doc and build by default (External dependencies are no longer required.) --- doc/manual/setupguide.tex | 4 -- examples/Makefile | 8 ---- .../{extra_board_usb => board_usb}/.gitignore | 0 .../{extra_board_usb => board_usb}/Makefile | 0 .../at90usb162_cdc_loopback.c | 0 .../at90usb162_cdc_loopback.h | 0 .../{extra_board_usb => board_usb}/simusb.c | 0 examples/extra_board_usb/README | 45 ------------------- 8 files changed, 57 deletions(-) rename examples/{extra_board_usb => board_usb}/.gitignore (100%) rename examples/{extra_board_usb => board_usb}/Makefile (100%) rename examples/{extra_board_usb => board_usb}/at90usb162_cdc_loopback.c (100%) rename examples/{extra_board_usb => board_usb}/at90usb162_cdc_loopback.h (100%) rename examples/{extra_board_usb => board_usb}/simusb.c (100%) delete mode 100644 examples/extra_board_usb/README diff --git a/doc/manual/setupguide.tex b/doc/manual/setupguide.tex index 194297ddd..d773bbd1e 100644 --- a/doc/manual/setupguide.tex +++ b/doc/manual/setupguide.tex @@ -37,10 +37,6 @@ \subsection{Software Dependencies} \item make 3.82 \end{itemize} -Furthermore, the board\_usb example depends on libusb\_vhci and vhci\_hcd. For -further details, see \emph{examples/board\_usb/README}. Note however that these -are not required for a fully working \simavr build. - \subsection{Compilation and Installation} \simavr's build system relies on standard makefiles. The simplest compilation diff --git a/examples/Makefile b/examples/Makefile index 65cc8933b..77bcb8fb2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -12,11 +12,3 @@ all: clean: for bi in ${boards}; do $(MAKE) -C $$bi clean; done - -# -# The USB example is not made by default, as it downloads stuff -# for the vhci library, it fails the debian policy on being able -# to build offline. -# -extra_board_usb: - make -C extra_board_usb diff --git a/examples/extra_board_usb/.gitignore b/examples/board_usb/.gitignore similarity index 100% rename from examples/extra_board_usb/.gitignore rename to examples/board_usb/.gitignore diff --git a/examples/extra_board_usb/Makefile b/examples/board_usb/Makefile similarity index 100% rename from examples/extra_board_usb/Makefile rename to examples/board_usb/Makefile diff --git a/examples/extra_board_usb/at90usb162_cdc_loopback.c b/examples/board_usb/at90usb162_cdc_loopback.c similarity index 100% rename from examples/extra_board_usb/at90usb162_cdc_loopback.c rename to examples/board_usb/at90usb162_cdc_loopback.c diff --git a/examples/extra_board_usb/at90usb162_cdc_loopback.h b/examples/board_usb/at90usb162_cdc_loopback.h similarity index 100% rename from examples/extra_board_usb/at90usb162_cdc_loopback.h rename to examples/board_usb/at90usb162_cdc_loopback.h diff --git a/examples/extra_board_usb/simusb.c b/examples/board_usb/simusb.c similarity index 100% rename from examples/extra_board_usb/simusb.c rename to examples/board_usb/simusb.c diff --git a/examples/extra_board_usb/README b/examples/extra_board_usb/README deleted file mode 100644 index 0db5550bc..000000000 --- a/examples/extra_board_usb/README +++ /dev/null @@ -1,45 +0,0 @@ -This will bridge the usb avr to the vhci-usb virtual usb host. - -You'll need vhci-usb and vhci-usb-lib to build and use it. -(http://sourceforge.net/projects/usb-vhci/) - -When setup, your avr project will connect to the linux usb system -as a real device. - -BUILDING usb-vhci ------------------ -git://usb-vhci.git.sourceforge.net/gitroot/usb-vhci/vhci_hcd - -The driver doesn't compile on recent linux kernels. -(commit 203800f0 Mon Apr 4) -0001-SPIN_LOCK_UNLOCKED-has-been-depreciated.patch -and -0002-need-transaction-translator.patch -should fix that. - -then simply "make && make install" - -might need to copy the api header file: -mkdir -p /usr/local/include/linux -sudo cp usb-vhci.h /usr/local/include/linux - - -BUILDING libusb_vhci --------------------- -git://usb-vhci.git.sourceforge.net/gitroot/usb-vhci/libusb_vhci - -This was a little more troublesome, but I didn't care to figure it out. -with libusb_vhci trunk (commit 5927f39a Sun Mar 27) - -add -0001-Comment-out-function-that-doesn-t-compile.patch -patch to remove that won't compile (and we don't use) -then: -cd src -gcc -c libusb_vhci.c -ar rcs libusb_vhci.a libusb_vhci.o -sudo cp libusb_vhci.a /usr/local/lib -mkdir -p /usr/local/include/linux -sudo cp libusb_vhci.h /usr/local/include/linux - -Gives us what we need From 02752183305a88c7c8a9bf22031ee1e1104d9a71 Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Thu, 7 Sep 2017 15:14:58 +0200 Subject: [PATCH 8/9] parts/vhci: remove, replaced by usbip --- examples/parts/vhci_usb.c | 414 ------------------ examples/parts/vhci_usb.h | 34 -- examples/vhci/.gitignore | 6 - examples/vhci/Makefile | 54 --- ...N_LOCK_UNLOCKED-has-been-depreciated.patch | 25 -- ...hcd-0002-need-transaction-translator.patch | 25 -- ...nt-out-function-that-doesn-t-compile.patch | 29 -- .../vhci-0002-need-unistd-for-usleep.patch | 11 - 8 files changed, 598 deletions(-) delete mode 100644 examples/parts/vhci_usb.c delete mode 100644 examples/parts/vhci_usb.h delete mode 100644 examples/vhci/.gitignore delete mode 100644 examples/vhci/Makefile delete mode 100644 examples/vhci/patches/hcd-0001-SPIN_LOCK_UNLOCKED-has-been-depreciated.patch delete mode 100644 examples/vhci/patches/hcd-0002-need-transaction-translator.patch delete mode 100644 examples/vhci/patches/vhci-0001-Comment-out-function-that-doesn-t-compile.patch delete mode 100644 examples/vhci/patches/vhci-0002-need-unistd-for-usleep.patch diff --git a/examples/parts/vhci_usb.c b/examples/parts/vhci_usb.c deleted file mode 100644 index 382555f1c..000000000 --- a/examples/parts/vhci_usb.c +++ /dev/null @@ -1,414 +0,0 @@ -/* vim: set sts=4:sw=4:ts=4:noexpandtab - vhci_usb.c - - Copyright 2012 Torbjorn Tyridal - - This file is part of simavr. - - simavr 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. - - simavr 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 simavr. If not, see . - */ - -/* - this avrsim part is an usb connection between an usb AVR and the virtual - host controller interface vhci-usb - making your sim-avr connect as a real - usb device to the developer machine. - - You'll need vhci-usb and libusb_vhci to make it work. - http://sourceforge.net/projects/usb-vhci/ -*/ - -/* TODO iso endpoint support */ - -#include "vhci_usb.h" -#include "libusb_vhci.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "avr_usb.h" - -static void -vhci_usb_attach_hook( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - struct vhci_usb_t * p = (struct vhci_usb_t*) param; - p->attached = !!value; - printf("avr attached: %d\n", p->attached); -} - -struct usbsetup { -uint8_t reqtype; uint8_t req; uint16_t wValue; uint16_t wIndex; uint16_t wLength; -}__attribute__((__packed__)); - -struct _ep { - uint8_t epnum; - uint8_t epsz; -}; - -char * setuprequests[] = - { "GET_STATUS", "CLEAR_FEAT", "", "SET_FEAT", "", "SET_ADDR", "GET_DESCR", - "SET_DESCR", "GET_CONF", "SET_CONF" }; - -static int -control_read( - struct vhci_usb_t * p, - struct _ep * ep, - uint8_t reqtype, - uint8_t req, - uint16_t wValue, - uint16_t wIndex, - uint16_t wLength, - uint8_t * data) -{ - assert(reqtype&0x80); - int ret; - struct usbsetup buf = - { reqtype, req, wValue, wIndex, wLength }; - struct avr_io_usb pkt = - { ep->epnum, sizeof(struct usbsetup), (uint8_t*) &buf }; - - avr_ioctl(p->avr, AVR_IOCTL_USB_SETUP, &pkt); - - pkt.sz = wLength; - pkt.buf = data; - while (wLength) { - usleep(1000); - ret = avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt); - if (ret == AVR_IOCTL_USB_NAK) { - printf(" NAK\n"); - usleep(50000); - continue; - } - if (ret == AVR_IOCTL_USB_STALL) { - printf(" STALL\n"); - return ret; - } - assert(ret==0); - pkt.buf += pkt.sz; - if (ep->epsz != pkt.sz) - break; - wLength -= pkt.sz; - pkt.sz = wLength; - } - wLength = pkt.buf - data; - - usleep(1000); - pkt.sz = 0; - while ((ret = avr_ioctl(p->avr, AVR_IOCTL_USB_WRITE, &pkt)) - == AVR_IOCTL_USB_NAK) { - usleep(50000); - } - assert(ret==0); - return wLength; -} - -static int -control_write( - struct vhci_usb_t * p, - struct _ep * ep, - uint8_t reqtype, - uint8_t req, - uint16_t wValue, - uint16_t wIndex, - uint16_t wLength, - uint8_t * data) -{ - assert((reqtype&0x80)==0); - int ret; - struct usbsetup buf = - { reqtype, req, wValue, wIndex, wLength }; - struct avr_io_usb pkt = - { ep->epnum, sizeof(struct usbsetup), (uint8_t*) &buf }; - - avr_ioctl(p->avr, AVR_IOCTL_USB_SETUP, &pkt); - usleep(10000); - - if (wLength > 0) { - pkt.sz = (wLength > ep->epsz ? ep->epsz : wLength); - pkt.buf = data; - while ((ret = avr_ioctl(p->avr, AVR_IOCTL_USB_WRITE, &pkt)) != 0) { - if (ret == AVR_IOCTL_USB_NAK) { - usleep(50000); - continue; - } - if (ret == AVR_IOCTL_USB_STALL) { - printf(" STALL\n"); - return ret; - } - assert(ret==0); - if (pkt.sz != ep->epsz) - break; - pkt.buf += pkt.sz; - wLength -= pkt.sz; - pkt.sz = (wLength > ep->epsz ? ep->epsz : wLength); - } - } - - pkt.sz = 0; - while ((ret = avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt)) - == AVR_IOCTL_USB_NAK) { - usleep(50000); - } - return ret; -} - -static void -handle_status_change( - struct vhci_usb_t * p, - struct usb_vhci_port_stat*prev, - struct usb_vhci_port_stat*curr) -{ - if (~prev->status & USB_VHCI_PORT_STAT_POWER - && curr->status & USB_VHCI_PORT_STAT_POWER) { - avr_ioctl(p->avr, AVR_IOCTL_USB_VBUS, (void*) 1); - if (p->attached) { - if (usb_vhci_port_connect(p->fd, 1, USB_VHCI_DATA_RATE_FULL) < 0) { - perror("port_connect"); - abort(); - } - } - } - if (prev->status & USB_VHCI_PORT_STAT_POWER - && ~curr->status & USB_VHCI_PORT_STAT_POWER) - avr_ioctl(p->avr, AVR_IOCTL_USB_VBUS, 0); - - if (curr->change & USB_VHCI_PORT_STAT_C_RESET - && ~curr->status & USB_VHCI_PORT_STAT_RESET - && curr->status & USB_VHCI_PORT_STAT_ENABLE) { -// printf("END OF RESET\n"); - } - if (~prev->status & USB_VHCI_PORT_STAT_RESET - && curr->status & USB_VHCI_PORT_STAT_RESET) { - avr_ioctl(p->avr, AVR_IOCTL_USB_RESET, NULL); - usleep(50000); - if (curr->status & USB_VHCI_PORT_STAT_CONNECTION) { - if (usb_vhci_port_reset_done(p->fd, 1, 1) < 0) { - perror("reset_done"); - abort(); - } - } - } - if (~prev->flags & USB_VHCI_PORT_STAT_FLAG_RESUMING - && curr->flags & USB_VHCI_PORT_STAT_FLAG_RESUMING) { - printf("port resuming\n"); - if (curr->status & USB_VHCI_PORT_STAT_CONNECTION) { - printf(" completing\n"); - if (usb_vhci_port_resumed(p->fd, 1) < 0) { - perror("resumed"); - abort(); - } - } - } - if (~prev->status & USB_VHCI_PORT_STAT_SUSPEND - && curr->status & USB_VHCI_PORT_STAT_SUSPEND) - printf("port suspedning\n"); - if (prev->status & USB_VHCI_PORT_STAT_ENABLE - && ~curr->status & USB_VHCI_PORT_STAT_ENABLE) - printf("port disabled\n"); - - *prev = *curr; -} - -static int -get_ep0_size( - struct vhci_usb_t * p) -{ - struct _ep ep0 = - { 0, 8 }; - uint8_t data[8]; - - int res = control_read(p, &ep0, 0x80, 6, 1 << 8, 0, 8, data); - assert(res==8); - return data[7]; -} - -static void -handle_ep0_control( - struct vhci_usb_t * p, - struct _ep * ep0, - struct usb_vhci_urb * urb) -{ - int res; - if (urb->bmRequestType &0x80) { - res = control_read(p,ep0, - urb->bmRequestType, - urb->bRequest, - urb->wValue, - urb->wIndex, - urb->wLength, - urb->buffer); - if (res>=0) { - urb->buffer_actual=res; - res=0; - } - } - else - res = control_write(p,ep0, - urb->bmRequestType, - urb->bRequest, - urb->wValue, - urb->wIndex, - urb->wLength, - urb->buffer); - - if (res==AVR_IOCTL_USB_STALL) - urb->status = USB_VHCI_STATUS_STALL; - else - urb->status = USB_VHCI_STATUS_SUCCESS; -} - -static void * -vhci_usb_thread( - void * param) -{ - struct vhci_usb_t * p = (struct vhci_usb_t*) param; - struct _ep ep0 = - { 0, 0 }; - struct usb_vhci_port_stat port_status; - int id, busnum; - char*busid; - p->fd = usb_vhci_open(1, &id, &busnum, &busid); - - if (p->fd < 0) { - perror("open vhci failed"); - printf("driver loaded, and access bits ok?\n"); - abort(); - } - printf("Created virtual usb host with 1 port at %s (bus# %d)\n", busid, - busnum); - memset(&port_status, 0, sizeof port_status); - - bool avrattached = false; - - for (unsigned cycle = 0;; cycle++) { - struct usb_vhci_work wrk; - - int res = usb_vhci_fetch_work(p->fd, &wrk); - - if (p->attached != avrattached) { - if (p->attached && port_status.status & USB_VHCI_PORT_STAT_POWER) { - if (usb_vhci_port_connect(p->fd, 1, USB_VHCI_DATA_RATE_FULL) - < 0) { - perror("port_connect"); - abort(); - } - } - if (!p->attached) { - ep0.epsz = 0; - //disconnect - } - avrattached = p->attached; - } - - if (res < 0) { - if (errno == ETIMEDOUT || errno == EINTR || errno == ENODATA) - continue; - perror("fetch work failed"); - abort(); - } - - switch (wrk.type) { - case USB_VHCI_WORK_TYPE_PORT_STAT: - handle_status_change(p, &port_status, &wrk.work.port_stat); - break; - case USB_VHCI_WORK_TYPE_PROCESS_URB: - if (!ep0.epsz) - ep0.epsz = get_ep0_size(p); - - wrk.work.urb.buffer = 0; - wrk.work.urb.iso_packets = 0; - if (wrk.work.urb.buffer_length) - wrk.work.urb.buffer = malloc(wrk.work.urb.buffer_length); - if (wrk.work.urb.packet_count) - wrk.work.urb.iso_packets = malloc( - wrk.work.urb.packet_count - * sizeof(struct usb_vhci_iso_packet)); - if (res) { - if (usb_vhci_fetch_data(p->fd, &wrk.work.urb) < 0) { - if (errno != ECANCELED) - perror("fetch_data"); - free(wrk.work.urb.buffer); - free(wrk.work.urb.iso_packets); - usb_vhci_giveback(p->fd, &wrk.work.urb); - break; - } - } - - if (usb_vhci_is_control(wrk.work.urb.type) - && !(wrk.work.urb.epadr & 0x7f)) { - handle_ep0_control(p, &ep0, &wrk.work.urb); - - } else { - struct avr_io_usb pkt = - { wrk.work.urb.epadr, wrk.work.urb.buffer_actual, - wrk.work.urb.buffer }; - if (usb_vhci_is_out(wrk.work.urb.epadr)) - res = avr_ioctl(p->avr, AVR_IOCTL_USB_WRITE, &pkt); - else { - pkt.sz = wrk.work.urb.buffer_length; - res = avr_ioctl(p->avr, AVR_IOCTL_USB_READ, &pkt); - wrk.work.urb.buffer_actual = pkt.sz; - } - if (res == AVR_IOCTL_USB_STALL) - wrk.work.urb.status = USB_VHCI_STATUS_STALL; - else if (res == AVR_IOCTL_USB_NAK) - wrk.work.urb.status = USB_VHCI_STATUS_TIMEDOUT; - else - wrk.work.urb.status = USB_VHCI_STATUS_SUCCESS; - } - if (usb_vhci_giveback(p->fd, &wrk.work.urb) < 0) - perror("giveback"); - free(wrk.work.urb.buffer); - free(wrk.work.urb.iso_packets); - break; - case USB_VHCI_WORK_TYPE_CANCEL_URB: - printf("cancel urb\n"); - break; - default: - printf("illegal work type\n"); - abort(); - } - - } -} - -void -vhci_usb_init( - struct avr_t * avr, - struct vhci_usb_t * p) -{ - p->avr = avr; - pthread_t thread; - - pthread_create(&thread, NULL, vhci_usb_thread, p); - -} - -void -vhci_usb_connect( - struct vhci_usb_t * p, - char uart) -{ - avr_irq_t * t = avr_io_getirq(p->avr, AVR_IOCTL_USB_GETIRQ(), - USB_IRQ_ATTACH); - avr_irq_register_notify(t, vhci_usb_attach_hook, p); -} - diff --git a/examples/parts/vhci_usb.h b/examples/parts/vhci_usb.h deleted file mode 100644 index 55d3012fc..000000000 --- a/examples/parts/vhci_usb.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - vhci_usb.h - - Copyright 2012 Torbjorn Tyridal - - This file is part of simavr. - - simavr 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. - - simavr 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 simavr. If not, see . - */ - -#include - -struct avr_t; -typedef struct vhci_usb_t { - struct avr_t * avr; - - bool attached; - int fd; -} vhci_usb_t; - - -void vhci_usb_connect(struct vhci_usb_t * p, char uart); -void vhci_usb_init(struct avr_t * avr, struct vhci_usb_t * p); diff --git a/examples/vhci/.gitignore b/examples/vhci/.gitignore deleted file mode 100644 index dec268127..000000000 --- a/examples/vhci/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -include -lib -linux -*.bz2 -libusb_vhci-* -vhci-hcd-* diff --git a/examples/vhci/Makefile b/examples/vhci/Makefile deleted file mode 100644 index 0164152c8..000000000 --- a/examples/vhci/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# -# This makefile attempts to compile the vhci core module and the -# libusb-vhci library by downloading known tarballs, hacking them -# a little and compiling them -# -# This has been tested on debian, but coild possibly work in other -# distro. the only "real" dependency is to have the linux kernel -# header symlinked at /lib/modules/ -Date: Sun, 19 Feb 2012 17:20:55 +0100 -Subject: [PATCH 1/2] SPIN_LOCK_UNLOCKED has been depreciated - ---- - usb-vhci-hcd.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/usb-vhci-hcd.c b/usb-vhci-hcd.c -index fed46aa..b107e1b 100644 ---- a/usb-vhci-hcd.c -+++ b/usb-vhci-hcd.c -@@ -1040,7 +1040,7 @@ static int device_enum(struct device *dev, void *data) - return unlikely(*((const int *)data) == pdev->id) ? -EINVAL : 0; - } - --static spinlock_t dev_enum_lock = SPIN_LOCK_UNLOCKED; -+static DEFINE_SPINLOCK(dev_enum_lock); - - int usb_vhci_hcd_register(const struct usb_vhci_ifc *ifc, void *context, u8 port_count, struct usb_vhci_device **vdev_ret) - { --- -1.7.5.4 - diff --git a/examples/vhci/patches/hcd-0002-need-transaction-translator.patch b/examples/vhci/patches/hcd-0002-need-transaction-translator.patch deleted file mode 100644 index 5dab784ca..000000000 --- a/examples/vhci/patches/hcd-0002-need-transaction-translator.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 11483dc8c623b93c1ab419a48387161abcf75a45 Mon Sep 17 00:00:00 2001 -From: root -Date: Sun, 19 Feb 2012 17:21:07 +0100 -Subject: [PATCH 2/2] need transaction translator - ---- - usb-vhci-hcd.c | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/usb-vhci-hcd.c b/usb-vhci-hcd.c -index b107e1b..fcb9755 100644 ---- a/usb-vhci-hcd.c -+++ b/usb-vhci-hcd.c -@@ -921,6 +921,8 @@ static int vhci_hcd_probe(struct platform_device *pdev) - if(unlikely(!hcd)) return -ENOMEM; - vdev->vhc = usbhcd_to_vhcihcd(hcd); - -+ hcd->has_tt=1; -+ - retval = usb_add_hcd(hcd, 0, 0); // calls vhci_start - if(unlikely(retval)) usb_put_hcd(hcd); - --- -1.7.5.4 - diff --git a/examples/vhci/patches/vhci-0001-Comment-out-function-that-doesn-t-compile.patch b/examples/vhci/patches/vhci-0001-Comment-out-function-that-doesn-t-compile.patch deleted file mode 100644 index 0db9beb37..000000000 --- a/examples/vhci/patches/vhci-0001-Comment-out-function-that-doesn-t-compile.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 8450b39ce40b2cc2e9e7cf3cfceaafdae2605f17 Mon Sep 17 00:00:00 2001 -From: Torbjorn Tyridal -Date: Thu, 23 Feb 2012 13:37:19 +0100 -Subject: [PATCH] Comment out function that doesn't compile - ---- - src/libusb_vhci.c | 8 ++++---- - 1 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/libusb_vhci.c b/src/libusb_vhci.c -index 47fc381..002d7aa 100644 ---- a/src/libusb_vhci.c -+++ b/src/libusb_vhci.c -@@ -389,8 +389,8 @@ int usb_vhci_to_iso_packets_errno(int32_t status) - return usb_vhci_to_errno(status, 0); - } - --int32_t usb_vhci_from_iso_packets_errno(int errno) --{ -- return usb_vhci_from_errno(errno, 0); --} -+// int32_t usb_vhci_from_iso_packets_errno(int errno) -+// { -+// return usb_vhci_from_errno(errno, 0); -+// } - --- -1.7.5.4 - diff --git a/examples/vhci/patches/vhci-0002-need-unistd-for-usleep.patch b/examples/vhci/patches/vhci-0002-need-unistd-for-usleep.patch deleted file mode 100644 index a33471bf9..000000000 --- a/examples/vhci/patches/vhci-0002-need-unistd-for-usleep.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -uwr libusb_vhci-0.6.orig/src/local_hcd.cpp libusb_vhci-0.6/src/local_hcd.cpp ---- libusb_vhci-0.6.orig/src/local_hcd.cpp 2012-05-18 11:52:17.097659487 +0100 -+++ libusb_vhci-0.6/src/local_hcd.cpp 2012-05-18 11:52:45.161659975 +0100 -@@ -21,6 +21,7 @@ - #endif - - #include -+#include - #include - #include "libusb_vhci.h" - From 262574de752ccb9f41efe73a6d0ded69bb02154a Mon Sep 17 00:00:00 2001 From: Torbjorn Tyridal Date: Mon, 18 Sep 2017 09:38:54 +0200 Subject: [PATCH 9/9] Add license headers to all files --- examples/parts/usb_types.h | 21 +++++++++++++++++++++ examples/parts/usbip_tester.py | 17 +++++++++++++++++ examples/parts/usbip_types.h | 22 ++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/examples/parts/usb_types.h b/examples/parts/usb_types.h index 182cd2f7d..b2c909556 100644 --- a/examples/parts/usb_types.h +++ b/examples/parts/usb_types.h @@ -1,3 +1,24 @@ +/* vim: set sts=4:sw=4:ts=4:noexpandtab + usb_types.h + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr 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. + + simavr 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 simavr. If not, see . +*/ + #include #define byte uint8_t diff --git a/examples/parts/usbip_tester.py b/examples/parts/usbip_tester.py index 9c7204022..19c764155 100755 --- a/examples/parts/usbip_tester.py +++ b/examples/parts/usbip_tester.py @@ -1,5 +1,22 @@ #!/usr/bin/env python3 # +# Copyright 2017 Torbjorn Tyridal +# +# This file is part of simavr. +# +# simavr 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. +# +# simavr 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 simavr. If not, see . +# # This is a quickly thrown together emulation of the kernel + usbip utilities # side of the usbip protocol # diff --git a/examples/parts/usbip_types.h b/examples/parts/usbip_types.h index e1c92cbd2..8a85153a0 100644 --- a/examples/parts/usbip_types.h +++ b/examples/parts/usbip_types.h @@ -1,3 +1,25 @@ +/* vim: set sts=4:sw=4:ts=4:noexpandtab + usbip_types.h + + Copyright 2017 Torbjorn Tyridal + + This file is part of simavr. + + simavr 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. + + simavr 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 simavr. If not, see . + +*/ + //ref https://github.com/torvalds/linux/blob/master/tools/usb/usbip //ref https://github.com/torvalds/linux/blob/master/drivers/usb/usbip