From cb0895f166b22d9e0026efe27d732ccd99ea4830 Mon Sep 17 00:00:00 2001 From: Abhijith Date: Thu, 10 Aug 2017 09:49:30 -0700 Subject: [PATCH] Moving UF2 related code away from this repo --- brick/Makefile | 12 - brick/README.md | 35 - brick/ins | 10 - brick/kernel/Makefile | 2 - brick/kernel/computil.c | 1383 -------------- brick/kernel/d_usbdev.c | 762 -------- brick/kernel/f_mass_storage.c | 3165 ------------------------------- brick/kernel/gadget_chips.h | 276 --- brick/kernel/source/am1808.h | 249 --- brick/kernel/source/bytecodes.h | 1744 ----------------- brick/kernel/source/c_branch.h | 81 - brick/kernel/source/c_compare.h | 81 - brick/kernel/source/c_math.h | 88 - brick/kernel/source/c_move.h | 76 - brick/kernel/source/c_timer.h | 38 - brick/kernel/source/lms2012.h | 1566 --------------- brick/kernel/source/lmstypes.h | 195 -- brick/kernel/source/validate.h | 56 - brick/kernel/storage_common.c | 779 -------- brick/kernel/usb_function.c | 738 ------- brick/mk | 7 - brick/scripts/README.md | 14 - brick/scripts/dump.js | 34 - brick/scripts/ev3-fs.patch | 53 - brick/scripts/img.js | 55 - brick/scripts/mkimg | 9 - brick/scripts/patchkern.js | 8 - brick/send | 10 - brick/uf2daemon/Makefile | 6 - brick/uf2daemon/fat.c | 784 -------- brick/uf2daemon/main.c | 231 --- brick/uf2daemon/uf2.h | 46 - brick/uf2daemon/uf2format.h | 48 - brick/uf2daemon/uf2hid.h | 106 -- 34 files changed, 12747 deletions(-) delete mode 100644 brick/Makefile delete mode 100644 brick/README.md delete mode 100755 brick/ins delete mode 100644 brick/kernel/Makefile delete mode 100644 brick/kernel/computil.c delete mode 100644 brick/kernel/d_usbdev.c delete mode 100644 brick/kernel/f_mass_storage.c delete mode 100644 brick/kernel/gadget_chips.h delete mode 100755 brick/kernel/source/am1808.h delete mode 100644 brick/kernel/source/bytecodes.h delete mode 100644 brick/kernel/source/c_branch.h delete mode 100644 brick/kernel/source/c_compare.h delete mode 100644 brick/kernel/source/c_math.h delete mode 100644 brick/kernel/source/c_move.h delete mode 100644 brick/kernel/source/c_timer.h delete mode 100755 brick/kernel/source/lms2012.h delete mode 100644 brick/kernel/source/lmstypes.h delete mode 100644 brick/kernel/source/validate.h delete mode 100644 brick/kernel/storage_common.c delete mode 100644 brick/kernel/usb_function.c delete mode 100755 brick/mk delete mode 100644 brick/scripts/README.md delete mode 100644 brick/scripts/dump.js delete mode 100644 brick/scripts/ev3-fs.patch delete mode 100644 brick/scripts/img.js delete mode 100755 brick/scripts/mkimg delete mode 100644 brick/scripts/patchkern.js delete mode 100755 brick/send delete mode 100644 brick/uf2daemon/Makefile delete mode 100644 brick/uf2daemon/fat.c delete mode 100644 brick/uf2daemon/main.c delete mode 100644 brick/uf2daemon/uf2.h delete mode 100644 brick/uf2daemon/uf2format.h delete mode 100644 brick/uf2daemon/uf2hid.h diff --git a/brick/Makefile b/brick/Makefile deleted file mode 100644 index 5b53e41d..00000000 --- a/brick/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -all: mod uf2 - -mod: - $(MAKE) -C .. MOD=d_usbdev M=`pwd`/kernel ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- - @mkdir -p bin - cp kernel/*.ko bin/ - -uf2: - $(MAKE) -C uf2daemon - @mkdir -p bin - cp uf2daemon/server bin/uf2d - diff --git a/brick/README.md b/brick/README.md deleted file mode 100644 index cbda2a10..00000000 --- a/brick/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Support code to run on EV3 brick - -## Kernel module - -Kernel module is based on LEGO's `d_usbdev` module, with the addition of slightly modified `g_mass_storage` -module from the Linux kernel. The module and supporting sources are licensed under GPLv2 (since -they are derived from GPLv2 code). - -### Modifications - -* the `d_usbdev` uses the composite framework to register an additional mass storage function in addtion - to the pre-existing custom USB HID function -* the `g_mass_storage` module has the following changes: - * additional `/sys/.../lun0/active` entry is added, which allows for signaling drive eject to the host -* `d_usbdev` has an additional `ioctl()` to pretend data came from the USB host - this can be used to direct - the VM to do stuff - -### Kernel modifications - -The kernel itself has modified FIFO queue sizes. The LEGO kernel uses `1024` for `ep1in` and `ep1out`, -and then `64` for `ep2` and `ep3`. Note that this is non-standard modification done with a kernel patch, -that I didn't manage to find. The MSD requires `512` for `ep2` and `ep3`. I have binary edited the kernel -to do so. - -Note that there's 4k of FIFO memory in the hardware. If you set the queue sizes with a sum of more than -4k, the kernel will hang, and you will not know why. - -## UF2 Daemon - -The [UF2](https://github.com/Microsoft/uf2) daemon is based on -[UF2 ATSAMD21](https://github.com/Microsoft/uf2-samd21) bootloader code. It exposes a virtual -FAT16 file system over Linux Network Block Device interface (`/dev/nbd0` to be precise). -This device is then exposed via the `g_mass_storage` module to the host computer. - -The Daemon is licensed under MIT. diff --git a/brick/ins b/brick/ins deleted file mode 100755 index 4444fe7f..00000000 --- a/brick/ins +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -ex -echo Y > /sys/module/printk/parameters/time -cd /mnt/ramdisk/prjs/ko -#echo 3 > /proc/sys/kernel/printk -insmod ./nbd.ko -sleep 1 -./uf2d /dev/nbd1 > /tmp/uf2d.log 2> /tmp/uf2derr.log -sleep 1 -insmod ./d_usbdev.ko file=/dev/nbd1 HostStr=EV3 SerialStr=0016535543af diff --git a/brick/kernel/Makefile b/brick/kernel/Makefile deleted file mode 100644 index 47510958..00000000 --- a/brick/kernel/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += $(MOD).o - diff --git a/brick/kernel/computil.c b/brick/kernel/computil.c deleted file mode 100644 index c2291d2e..00000000 --- a/brick/kernel/computil.c +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * This Composite Utility file is based on and inheritated from - * the original file and work done by David Brownell - * - * >> composite.c - infrastructure for Composite USB Gadgets << - * >> Copyright (C) 2006-2008 David Brownell << - * - */ - -#ifndef PCASM -#include -#include -#include -#include - -#include -#else -// Keep Eclipse happy -#endif - -#if 1 -#undef dev_vdbg -#undef dev_dbg -#define dev_vdbg(d, args...) printk(args) -#define dev_dbg(d, args...) printk(args) -#endif - -/* big enough to hold our biggest descriptor */ -#define USB_BUFSIZ 1024 - -USB_SPEED UsbSpeed; // We will only be HIGH speed if device is connected to a HIGH - // speed HOST (make no sense to use FULL speed for PC connectivity.) - // FULL speed is necessary due to the fact, that we only have a 12 - // Mbit HOST port on the brick (I.e. FULL speed HOST) -static USB_SPEED UsbSpeedDefault; -static USB_SPEED *pUsbSpeed = &UsbSpeedDefault; -/* - * The code in this file is utility code, used to build a gadget driver - * from one or more "function" drivers, one or more "configuration" - * objects, and a "usb_composite_driver" by gluing them together along - * with the relevant device-wide data. - */ - -static struct usb_composite_driver *composite; - -/* Some systems will need runtime overrides for the product identifers - * published in the device descriptor, either numbers or strings or both. - * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). - */ -#ifndef PCASM -static ushort idVendor; -module_param(idVendor, ushort, 0); -MODULE_PARM_DESC(idVendor, "USB Vendor ID"); - -static ushort idProduct; -module_param(idProduct, ushort, 0); -MODULE_PARM_DESC(idProduct, "USB Product ID"); - -static ushort bcdDevice; -module_param(bcdDevice, ushort, 0); -MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); - -static char *iManufacturer; -module_param(iManufacturer, charp, 0); -MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); - -static char *iProduct; -module_param(iProduct, charp, 0); -MODULE_PARM_DESC(iProduct, "USB Product string"); - -static char *iSerialNumber; -module_param(iSerialNumber, charp, 0); -MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); -#else -// Keep Eclipse happy -#endif - -/*HIGH SPEED hid descriptor */ /* Size = 29 decimal */ -static char hs_hid_report_descriptor[] = { - 0x06, 0x00, 0xFF, // Usage page (vendor defined) - 0x09, 0x01, // Usage ID (vendor defined) - 0xA1, 0x01, // Collection (application) - - // The Input report - 0x15, 0x00, // Logical Minimum (0) - 0x26, 0xFF, 0x00, // Logical Maximum (255) - 0x75, 0x08, // Report Size (8 bits) - - 0x96, 0x00, 0x04, // Report Count (1024 fields) - 0x09, 0x01, // USAGE (vendor usage 1) - 0x81, 0x02, // Input (Data, Variable, Absolute) - - 0x96, 0x00, 0x04, // Report Count (1024 fields) - 0x09, 0x01, // USAGE (vendor usage 1) - 0x91, 0x02, // Output (Data, Variable, Absolute) - - 0xc0 /* END_COLLECTION */ - - -}; - -/*LOW SPEED hid descriptor */ /* Size = 29 decimal */ -static char fs_hid_report_descriptor[] = { - 0x06, 0x00, 0xFF, // Usage page (vendor defined) - 0x09, 0x01, // Usage ID (vendor defined) - 0xA1, 0x01, // Collection (application) - - // The Input report - 0x15, 0x00, // Logical Minimum (0) - 0x26, 0xFF, 0x00, // Logical Maximum (255) - 0x75, 0x08, // Report Size (8 bits) - - 0x96, 0x40, 0x00, // Report Count (64 fields) - 0x09, 0x01, // USAGE (vendor usage 1) - 0x81, 0x02, // Input (Data, Variable, Absolute) - - 0x96, 0x40, 0x00, // Report Count (64 fields) - 0x09, 0x01, // USAGE (vendor usage 1) - 0x91, 0x02, // Output (Data, Variable, Absolute) - - 0xc0 /* END_COLLECTION */ - -}; - - -/*-------------------------------------------------------------------------*/ - -/** - * usb_add_function() - add a function to a configuration - * @config: the configuration - * @function: the function being added - * Context: single threaded during gadget setup - * - * After initialization, each configuration must have one or more - * functions added to it. Adding a function involves calling its @bind() - * method to allocate resources such as interface and string identifiers - * and endpoints. - * - * This function returns the value of the function's bind(), which is - * zero for success else a negative errno value. - */ - -int usb_add_function(struct usb_configuration *config, - struct usb_function *function) -{ - int value = -EINVAL; - - DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n", - function->name, function, - config->label, config); - - if (!function->set_alt || !function->disable) - goto done; - - function->config = config; - list_add_tail(&function->list, &config->functions); - - /* REVISIT *require* function->bind? */ - if (function->bind) { - value = function->bind(config, function); - if (value < 0) { - list_del(&function->list); - function->config = NULL; - } - } else - value = 0; - - /* We allow configurations that don't work at both speeds. - * If we run into a lowspeed Linux system, treat it the same - * as full speed ... it's the function drivers that will need - * to avoid bulk and ISO transfers. - */ - if (!config->fullspeed && function->descriptors) - config->fullspeed = true; - if (!config->highspeed && function->hs_descriptors) - config->highspeed = true; - -done: - if (value) - DBG(config->cdev, "adding '%s'/%p --> %d\n", - function->name, function, value); - return value; -} - -/* - * usb_function_deactivate - prevent function and gadget enumeration - * @function: the function that isn't yet ready to respond - * - * Blocks response of the gadget driver to host enumeration by - * preventing the data line pullup from being activated. This is - * normally called during @bind() processing to change from the - * initial "ready to respond" state, or when a required resource - * becomes available. - * - * For example, drivers that serve as a passthrough to a userspace - * daemon can block enumeration unless that daemon (such as an OBEX, - * MTP, or print server) is ready to handle host requests. - * - * Not all systems support software control of their USB peripheral - * data pullups. - * - * Returns zero on success, else negative errno. - */ -int usb_function_deactivate(struct usb_function *function) -{ - struct usb_composite_dev *cdev = function->config->cdev; - unsigned long flags; - int status = 0; - - spin_lock_irqsave(&cdev->lock, flags); - - if (cdev->deactivations == 0) - status = usb_gadget_disconnect(cdev->gadget); - if (status == 0) - cdev->deactivations++; - - spin_unlock_irqrestore(&cdev->lock, flags); - return status; -} - -/* - * usb_function_activate - allow function and gadget enumeration - * @function: function on which usb_function_activate() was called - * - * Reverses effect of usb_function_deactivate(). If no more functions - * are delaying their activation, the gadget driver will respond to - * host enumeration procedures. - * - * Returns zero on success, else negative errno. - */ -int usb_function_activate(struct usb_function *function) -{ - struct usb_composite_dev *cdev = function->config->cdev; - int status = 0; - - spin_lock(&cdev->lock); - - if (WARN_ON(cdev->deactivations == 0)) - status = -EINVAL; - else { - cdev->deactivations--; - if (cdev->deactivations == 0) - status = usb_gadget_connect(cdev->gadget); - } - - spin_unlock(&cdev->lock); - return status; -} - -/** - * usb_interface_id() - allocate an unused interface ID - * @config: configuration associated with the interface - * @function: function handling the interface - * Context: single threaded during gadget setup - * - * usb_interface_id() is called from usb_function.bind() callbacks to - * allocate new interface IDs. The function driver will then store that - * ID in interface, association, CDC union, and other descriptors. It - * will also handle any control requests targetted at that interface, - * particularly changing its altsetting via set_alt(). There may - * also be class-specific or vendor-specific requests to handle. - * - * All interface identifier should be allocated using this routine, to - * ensure that for example different functions don't wrongly assign - * different meanings to the same identifier. Note that since interface - * identifers are configuration-specific, functions used in more than - * one configuration (or more than once in a given configuration) need - * multiple versions of the relevant descriptors. - * - * Returns the interface ID which was allocated; or -ENODEV if no - * more interface IDs can be allocated. - */ - -int usb_interface_id(struct usb_configuration *config, - struct usb_function *function) -{ - unsigned id = config->next_interface_id; - - if (id < MAX_CONFIG_INTERFACES) { - config->interface[id] = function; - config->next_interface_id = id + 1; - return id; - } - return -ENODEV; -} - -#ifndef PCASM -static int config_buf(struct usb_configuration *config, - enum usb_device_speed speed, void *buf, u8 type) -{ - struct usb_config_descriptor *c = buf; - void *next = buf + USB_DT_CONFIG_SIZE; - int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; - struct usb_function *f; - int status; - - /* write the config descriptor */ - c = buf; - c->bLength = USB_DT_CONFIG_SIZE; - c->bDescriptorType = type; - /* wTotalLength is written later */ - c->bNumInterfaces = config->next_interface_id; // CTRL version was set to 2 - c->bConfigurationValue = config->bConfigurationValue; - c->iConfiguration = config->iConfiguration; - c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; - c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2); - - /* There may be e.g. OTG descriptors */ - if (config->descriptors) { - status = usb_descriptor_fillbuf(next, len, - config->descriptors); - if (status < 0) - return status; - len -= status; - next += status; - } - - /* add each function's descriptors */ - - list_for_each_entry(f, &config->functions, list) { - struct usb_descriptor_header **descriptors; - - if (speed == USB_SPEED_HIGH) - { - descriptors = f->hs_descriptors; - } - else - { - descriptors = f->descriptors; - } - - if (!descriptors) - continue; - status = usb_descriptor_fillbuf(next, len, - (const struct usb_descriptor_header **) descriptors); - if (status < 0) - return status; - len -= status; - next += status; - } - - len = next - buf; - c->wTotalLength = cpu_to_le16(len); - return len; -} -#else -// Keep Eclipse happy -#endif - -#ifndef PCASM - -static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) -{ - struct usb_gadget *gadget = cdev->gadget; - struct usb_configuration *c; - u8 type = w_value >> 8; - enum usb_device_speed speed = USB_SPEED_UNKNOWN; - - if (gadget_is_dualspeed(gadget)) { - int hs = 0; - - /*if (gadget->speed == USB_SPEED_HIGH) - hs = 1; - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - if (hs) - speed = USB_SPEED_HIGH; - */ - - if (gadget->speed == USB_SPEED_HIGH) - { - hs = 1; - UsbSpeed.Speed = HIGH_SPEED; - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("Speed = HIGH\n\r"); - #endif - } - else - { - hs = 0; - UsbSpeed.Speed = FULL_SPEED; - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("Speed = LOW\n\r"); - #endif - } - - if (type == USB_DT_OTHER_SPEED_CONFIG) - hs = !hs; - if (hs) - speed = USB_SPEED_HIGH; - } - - /* This is a lookup by config *INDEX* */ - w_value &= 0xff; - list_for_each_entry(c, &cdev->configs, list) { - /* ignore configs that won't work at this speed */ - if (speed == USB_SPEED_HIGH) { - if (!c->highspeed) - continue; - } else { - if (!c->fullspeed) - continue; - } - if (w_value == 0) - return config_buf(c, speed, cdev->req->buf, type); - w_value--; - } - return -EINVAL; -} -#else -// Keep Eclipse happy -#endif - -#ifndef PCASM -static int count_configs(struct usb_composite_dev *cdev, unsigned type) -{ - struct usb_gadget *gadget = cdev->gadget; - struct usb_configuration *c; - unsigned count = 0; - int hs = 0; - - if (gadget_is_dualspeed(gadget)) { - if (gadget->speed == USB_SPEED_HIGH) - hs = 1; - if (type == USB_DT_DEVICE_QUALIFIER) - hs = !hs; - } - list_for_each_entry(c, &cdev->configs, list) { - /* ignore configs that won't work at this speed */ - if (hs) { - if (!c->highspeed) - continue; - } else { - if (!c->fullspeed) - continue; - } - count++; - } - return count; -} -#else -// Keep Eclipse happy -#endif - -static void device_qual(struct usb_composite_dev *cdev) -{ - struct usb_qualifier_descriptor *qual = cdev->req->buf; - - qual->bLength = sizeof(*qual); - qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; - /* POLICY: same bcdUSB and device type info at both speeds */ - qual->bcdUSB = cdev->desc.bcdUSB; - qual->bDeviceClass = cdev->desc.bDeviceClass; - qual->bDeviceSubClass = cdev->desc.bDeviceSubClass; - qual->bDeviceProtocol = cdev->desc.bDeviceProtocol; - /* ASSUME same EP0 fifo size at both speeds */ - qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0; - qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER); - qual->bRESERVED = 0; -} - -/*-------------------------------------------------------------------------*/ -#ifndef PCASM -static void reset_config(struct usb_composite_dev *cdev) -{ - struct usb_function *f; - - DBG(cdev, "reset config\n"); - - list_for_each_entry(f, &cdev->config->functions, list) { - if (f->disable) - f->disable(f); - - bitmap_zero(f->endpoints, 32); - } - cdev->config = NULL; -} -#else -// Keep Eclipse happy -#endif - -#ifndef PCASM -static int set_config(struct usb_composite_dev *cdev, - const struct usb_ctrlrequest *ctrl, unsigned number) -{ - struct usb_gadget *gadget = cdev->gadget; - struct usb_configuration *c = NULL; - int result = -EINVAL; - unsigned power = gadget_is_otg(gadget) ? 8 : 100; - int tmp; - - if (cdev->config) - reset_config(cdev); - - if (number) { - list_for_each_entry(c, &cdev->configs, list) { - if (c->bConfigurationValue == number) { - result = 0; - break; - } - } - if (result < 0) - goto done; - } else - result = 0; - - /*INFO(cdev, "%s speed config #%d: %s\n", - ({ char *speed; - switch (gadget->speed) { - case USB_SPEED_LOW: speed = "low"; break; - case USB_SPEED_FULL: speed = "full"; break; - case USB_SPEED_HIGH: speed = "high"; break; - default: speed = "?"; break; - } ; speed; }), number, c ? c->label : "unconfigured"); -*/ - - if (!c) - goto done; - - cdev->config = c; - - /* Initialize all interfaces by setting them to altsetting zero. */ - for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { - struct usb_function *f = c->interface[tmp]; - struct usb_descriptor_header **descriptors; - - if (!f) - break; - - /* - * Record which endpoints are used by the function. This is used - * to dispatch control requests targeted at that endpoint to the - * function's setup callback instead of the current - * configuration's setup callback. - */ - - if (gadget->speed == USB_SPEED_HIGH) - descriptors = f->hs_descriptors; - else - descriptors = f->descriptors; - - for (; *descriptors; ++descriptors) { - struct usb_endpoint_descriptor *ep; - int addr; - - if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT) - continue; - - ep = (struct usb_endpoint_descriptor *)*descriptors; - addr = ((ep->bEndpointAddress & 0x80) >> 3) - | (ep->bEndpointAddress & 0x0f); - set_bit(addr, f->endpoints); - } - - result = f->set_alt(f, tmp, 0); - - - - if (result < 0) { - DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", - tmp, f->name, f, result); - - reset_config(cdev); - - goto done; - } - } - - /* when we return, be sure our power usage is valid */ - power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; -done: - usb_gadget_vbus_draw(gadget, power); - return result; -} - -#else -// Keep Eclipse happy -#endif - - -/** - * usb_add_config() - add a configuration to a device. - * @cdev: wraps the USB gadget - * @config: the configuration, with bConfigurationValue assigned - * Context: single threaded during gadget setup - * - * One of the main tasks of a composite driver's bind() routine is to - * add each of the configurations it supports, using this routine. - * - * This function returns the value of the configuration's bind(), which - * is zero for success else a negative errno value. Binding configurations - * assigns global resources including string IDs, and per-configuration - * resources such as interface IDs and endpoints. - */ - -#ifndef PCASM -int usb_add_config(struct usb_composite_dev *cdev, - struct usb_configuration *config) -{ - int status = -EINVAL; - struct usb_configuration *c; - - DBG(cdev, "adding config #%u '%s'/%p\n", - config->bConfigurationValue, - config->label, config); - - if (!config->bConfigurationValue || !config->bind) - goto done; - - /* Prevent duplicate configuration identifiers */ - list_for_each_entry(c, &cdev->configs, list) { - if (c->bConfigurationValue == config->bConfigurationValue) { - status = -EBUSY; - goto done; - } - } - - config->cdev = cdev; - list_add_tail(&config->list, &cdev->configs); - - INIT_LIST_HEAD(&config->functions); - config->next_interface_id = 0; - - status = config->bind(config); - if (status < 0) { - list_del(&config->list); - config->cdev = NULL; - } else { - unsigned i; - - DBG(cdev, "cfg %d/%p speeds:%s%s\n", - config->bConfigurationValue, config, - config->highspeed ? " high" : "", - config->fullspeed - ? (gadget_is_dualspeed(cdev->gadget) - ? " full" - : " full/low") - : ""); - - for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { - struct usb_function *f = config->interface[i]; - - if (!f) - continue; - DBG(cdev, " interface %d = %s/%p\n", - i, f->name, f); - } - } - - /* set_alt(), or next config->bind(), sets up - * ep->driver_data as needed. - */ - usb_ep_autoconfig_reset(cdev->gadget); - -done: - if (status) - DBG(cdev, "added config '%s'/%u --> %d\n", config->label, - config->bConfigurationValue, status); - return status; -} -#else -// Keep Eclipse happy -#endif - -/*-------------------------------------------------------------------------*/ - -/* We support strings in multiple languages ... string descriptor zero - * says which languages are supported. The typical case will be that - * only one language (probably English) is used, with I18N handled on - * the host side. - */ - -static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) -{ - const struct usb_gadget_strings *s; - u16 language; - __le16 *tmp; - - while (*sp) { - s = *sp; - language = cpu_to_le16(s->language); - for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) { - if (*tmp == language) - goto repeat; - } - *tmp++ = language; -repeat: - sp++; - } -} - -static int lookup_string( - struct usb_gadget_strings **sp, - void *buf, - u16 language, - int id -) -{ - struct usb_gadget_strings *s; - int value; - - while (*sp) { - s = *sp++; - if (s->language != language) - continue; - value = usb_gadget_get_string(s, id, buf); - if (value > 0) - return value; - } - return -EINVAL; -} - -#ifndef PCASM -static int get_string(struct usb_composite_dev *cdev, - void *buf, u16 language, int id) -{ - struct usb_configuration *c; - struct usb_function *f; - int len; - - /* Yes, not only is USB's I18N support probably more than most - * folk will ever care about ... also, it's all supported here. - * (Except for UTF8 support for Unicode's "Astral Planes".) - */ - - /* 0 == report all available language codes */ - if (id == 0) { - struct usb_string_descriptor *s = buf; - struct usb_gadget_strings **sp; - - memset(s, 0, 256); - s->bDescriptorType = USB_DT_STRING; - - sp = composite->strings; - if (sp) - collect_langs(sp, s->wData); - - list_for_each_entry(c, &cdev->configs, list) { - sp = c->strings; - if (sp) - collect_langs(sp, s->wData); - - list_for_each_entry(f, &c->functions, list) { - sp = f->strings; - if (sp) - collect_langs(sp, s->wData); - } - } - - for (len = 0; len <= 126 && s->wData[len]; len++) - continue; - if (!len) - return -EINVAL; - - s->bLength = 2 * (len + 1); - return s->bLength; - } - - /* Otherwise, look up and return a specified string. String IDs - * are device-scoped, so we look up each string table we're told - * about. These lookups are infrequent; simpler-is-better here. - */ - if (composite->strings) { - len = lookup_string(composite->strings, buf, language, id); - if (len > 0) - return len; - } - list_for_each_entry(c, &cdev->configs, list) { - if (c->strings) { - len = lookup_string(c->strings, buf, language, id); - if (len > 0) - return len; - } - list_for_each_entry(f, &c->functions, list) { - if (!f->strings) - continue; - len = lookup_string(f->strings, buf, language, id); - if (len > 0) - return len; - } - } - return -EINVAL; -} -#else -// Keep Eclipse happy -#endif - -/** - * usb_string_id() - allocate an unused string ID - * @cdev: the device whose string descriptor IDs are being allocated - * Context: single threaded during gadget setup - * - * @usb_string_id() is called from bind() callbacks to allocate - * string IDs. Drivers for functions, configurations, or gadgets will - * then store that ID in the appropriate descriptors and string table. - * - * All string identifier should be allocated using this routine, to - * ensure that for example different functions don't wrongly assign - * different meanings to the same identifier. - */ - -int usb_string_id(struct usb_composite_dev *cdev) -{ - if (cdev->next_string_id < 254) { - /* string id 0 is reserved */ - cdev->next_string_id++; - return cdev->next_string_id; - } - return -ENODEV; -} - -/*-------------------------------------------------------------------------*/ - -static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) - DBG((struct usb_composite_dev *) ep->driver_data, - "setup complete --> %d, %d/%d\n", - req->status, req->actual, req->length); -} - -/* - * The setup() callback implements all the ep0 functionality that's - * not handled lower down, in hardware or the hardware driver(like - * device and endpoint feature flags, and their status). It's all - * housekeeping for the gadget function we're implementing. Most of - * the work is in config and function specific setup. - */ - -#ifndef PCASM -static int -composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_request *req = cdev->req; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u8 intf = w_index & 0xFF; - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - struct usb_function *f = NULL; - u8 endp; - - /* partial re-init of the response message; the function or the - * gadget might need to intercept e.g. a control-OUT completion - * when we delegate to it. - */ - req->zero = 0; - req->complete = composite_setup_complete; - req->length = USB_BUFSIZ; - gadget->ep0->driver_data = cdev; - - - VDBG(cdev, - "setup req %02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - -switch (ctrl->bRequest) { - /* we handle all standard USB descriptors */ - case USB_REQ_GET_DESCRIPTOR: - - if ((ctrl->bRequestType != USB_DIR_IN) && (ctrl->bRequestType != 0x81)) - goto unknown; - - switch (w_value >> 8) { - - case USB_DT_DEVICE: // - - cdev->desc.bNumConfigurations = - count_configs(cdev, USB_DT_DEVICE); - value = min(w_length, (u16) sizeof cdev->desc); - memcpy(req->buf, &cdev->desc, value); - - break; - case USB_DT_DEVICE_QUALIFIER: - - if (!gadget_is_dualspeed(gadget)) - break; - device_qual(cdev); - value = min_t(int, w_length, - sizeof(struct usb_qualifier_descriptor)); - - break; - case USB_DT_OTHER_SPEED_CONFIG: - - if (!gadget_is_dualspeed(gadget)) - break; - /* FALLTHROUGH */ - case USB_DT_CONFIG: - - value = config_desc(cdev, w_value); - if (value >= 0) - value = min(w_length, (u16) value); - break; - case USB_DT_STRING: - - value = get_string(cdev, req->buf, - w_index, w_value & 0xff); - if (value >= 0) - value = min(w_length, (u16) value); - break; - - case 34: - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("\nWE are in GET_REPORT_DESC !! SETUP in COMPUTIL.C - case 34"); - #endif - - if(UsbSpeed.Speed == HIGH_SPEED) - { - memcpy(req->buf, hs_hid_report_descriptor, 29); - - #ifdef DEBUG - printk("\nWE are @ HIGH REPORT_DESC !!"); - #endif - } - else - { - memcpy(req->buf, fs_hid_report_descriptor, 29); - - #ifdef DEBUG - printk("\nWE are @ FULL REPORT_DESC !!"); - #endif - } - value =29; - break; - } - break; - - /* any number of configs can work */ - case USB_REQ_SET_CONFIGURATION: - - if (ctrl->bRequestType != 0) - goto unknown; - - if (gadget_is_otg(gadget)) { - - if (gadget->a_hnp_support) - DBG(cdev, "HNP available\n"); - else if (gadget->a_alt_hnp_support) - DBG(cdev, "HNP on another port\n"); - else - VDBG(cdev, "HNP inactive\n"); - } - - spin_lock(&cdev->lock); - value = set_config(cdev, ctrl, w_value); - - spin_unlock(&cdev->lock); - break; - case USB_REQ_GET_CONFIGURATION: - - if (ctrl->bRequestType != USB_DIR_IN) - goto unknown; - - if (cdev->config) - *(u8 *)req->buf = cdev->config->bConfigurationValue; - else - *(u8 *)req->buf = 0; - value = min(w_length, (u16) 1); - break; - - /* function drivers must handle get/set altsetting; if there's - * no get() method, we know only altsetting zero works. - */ - case USB_REQ_SET_INTERFACE: - - if (ctrl->bRequestType != USB_RECIP_INTERFACE) - goto unknown; - - if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) - break; - - f = cdev->config->interface[intf]; - if (!f) - break; - - if (w_value && !f->set_alt) - break; - - value = f->set_alt(f, w_index, w_value); - break; - case USB_REQ_GET_INTERFACE: - - if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) - goto unknown; - - if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) - break; - - f = cdev->config->interface[intf]; - if (!f) - break; - - /* lots of interfaces only need altsetting zero... */ - value = f->get_alt ? f->get_alt(f, w_index) : 0; - if (value < 0) - break; - - *((u8 *)req->buf) = value; - value = min(w_length, (u16) 1); - break; - default: -unknown: - VDBG(cdev, - "non-core control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - - /* functions always handle their interfaces and endpoints... - * punt other recipients (other, WUSB, ...) to the current - * configuration code. - * - * REVISIT it could make sense to let the composite device - * take such requests too, if that's ever needed: to work - * in config 0, etc. - */ - switch (ctrl->bRequestType & USB_RECIP_MASK) { - - case USB_RECIP_INTERFACE: - - f = cdev->config->interface[intf]; - break; - - case USB_RECIP_ENDPOINT: - - endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f); - list_for_each_entry(f, &cdev->config->functions, list) { - if (test_bit(endp, f->endpoints)) - break; - } - - if (&f->list == &cdev->config->functions) - f = NULL; - break; - } - - if (f && f->setup) - value = f->setup(f, ctrl); - else { - - struct usb_configuration *c; - - c = cdev->config; - if (c && c->setup) - value = c->setup(c, ctrl); - } - - goto done; - } - - /* respond with data transfer before status phase? */ - if (value >= 0) { - - req->length = value; - req->zero = value < w_length; - value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - - if (value < 0) { - DBG(cdev, "ep_queue --> %d\n", value); - req->status = 0; - composite_setup_complete(gadget->ep0, req); - } - } - -done: - - /* device either stalls (value < 0) or reports success */ - - return value; - -} -#else -// Keep Eclipse happy -#endif - - -static void composite_disconnect(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - unsigned long flags; - - /* REVISIT: should we have config and device level - * disconnect callbacks? - */ - - spin_lock_irqsave(&cdev->lock, flags); - if (cdev->config) - reset_config(cdev); - spin_unlock_irqrestore(&cdev->lock, flags); -} - -/*-------------------------------------------------------------------------*/ -#ifndef PCASM -static void /* __init_or_exit */ -composite_unbind(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - - /* composite_disconnect() must already have been called - * by the underlying peripheral controller driver! - * so there's no i/o concurrency that could affect the - * state protected by cdev->lock. - */ - WARN_ON(cdev->config); - - while (!list_empty(&cdev->configs)) { - struct usb_configuration *c; - - c = list_first_entry(&cdev->configs, - struct usb_configuration, list); - while (!list_empty(&c->functions)) { - struct usb_function *f; - - f = list_first_entry(&c->functions, - struct usb_function, list); - list_del(&f->list); - if (f->unbind) { - DBG(cdev, "unbind function '%s'/%p\n", - f->name, f); - f->unbind(c, f); - /* may free memory for "f" */ - } - } - list_del(&c->list); - if (c->unbind) { - DBG(cdev, "unbind config '%s'/%p\n", c->label, c); - c->unbind(c); - /* may free memory for "c" */ - } - } - if (composite->unbind) - composite->unbind(cdev); - - if (cdev->req) { - kfree(cdev->req->buf); - usb_ep_free_request(gadget->ep0, cdev->req); - } - kfree(cdev); - set_gadget_data(gadget, NULL); - composite = NULL; -} -#else -// Keep Eclipse happy -#endif - -static void -string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s) -{ - struct usb_string *str = tab->strings; - - for (str = tab->strings; str->s; str++) { - if (str->id == id) { - str->s = s; - return; - } - } -} - -static void -string_override(struct usb_gadget_strings **tab, u8 id, const char *s) -{ - while (*tab) { - string_override_one(*tab, id, s); - tab++; - } -} - -static int composite_bind(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev; - int status = -ENOMEM; - - cdev = kzalloc(sizeof *cdev, GFP_KERNEL); - if (!cdev) - return status; - - spin_lock_init(&cdev->lock); - cdev->gadget = gadget; - set_gadget_data(gadget, cdev); - INIT_LIST_HEAD(&cdev->configs); - - /* preallocate control response and buffer */ - cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); - if (!cdev->req) - goto fail; - cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); - if (!cdev->req->buf) - goto fail; - cdev->req->complete = composite_setup_complete; - gadget->ep0->driver_data = cdev; - - cdev->bufsiz = USB_BUFSIZ; - cdev->driver = composite; - - usb_gadget_set_selfpowered(gadget); - - /* interface and string IDs start at zero via kzalloc. - * we force endpoints to start unassigned; few controller - * drivers will zero ep->driver_data. - */ - usb_ep_autoconfig_reset(cdev->gadget); - - /* composite gadget needs to assign strings for whole device (like - * serial number), register function drivers, potentially update - * power state and consumption, etc - */ - status = composite->bind(cdev); - if (status < 0) - goto fail; - - cdev->desc = *composite->dev; - cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - - /* standardized runtime overrides for device ID data */ - if (idVendor) - cdev->desc.idVendor = cpu_to_le16(idVendor); - if (idProduct) - cdev->desc.idProduct = cpu_to_le16(idProduct); - if (bcdDevice) - cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); - - /* strings can't be assigned before bind() allocates the - * releavnt identifiers - */ - if (cdev->desc.iManufacturer && iManufacturer) - string_override(composite->strings, - cdev->desc.iManufacturer, iManufacturer); - if (cdev->desc.iProduct && iProduct) - string_override(composite->strings, - cdev->desc.iProduct, iProduct); - if (cdev->desc.iSerialNumber && iSerialNumber) - string_override(composite->strings, - cdev->desc.iSerialNumber, iSerialNumber); - - // INFO(cdev, "%s ready\n", composite->name); - return 0; - -fail: - composite_unbind(gadget); - return status; -} - -/*-------------------------------------------------------------------------*/ - -#ifndef PCASM -static void -composite_suspend(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_function *f; - - /* REVISIT: should we have config level - * suspend/resume callbacks? - */ - DBG(cdev, "suspend\n"); - if (cdev->config) { - list_for_each_entry(f, &cdev->config->functions, list) { - if (f->suspend) - f->suspend(f); - } - } - if (composite->suspend) - composite->suspend(cdev); -} -#else -// Keep Eclipse happy -#endif - -#ifndef PCASM -static void -composite_resume(struct usb_gadget *gadget) -{ - struct usb_composite_dev *cdev = get_gadget_data(gadget); - struct usb_function *f; - - /* REVISIT: should we have config level - * suspend/resume callbacks? - */ - DBG(cdev, "resume\n"); - if (composite->resume) - composite->resume(cdev); - if (cdev->config) { - list_for_each_entry(f, &cdev->config->functions, list) { - if (f->resume) - f->resume(f); - } - } -} -#else -// Keep Eclipse happy -#endif - -/*-------------------------------------------------------------------------*/ - -static struct usb_gadget_driver composite_driver = { - .speed = USB_SPEED_HIGH, - - .bind = composite_bind, - /* .unbind = __exit_p(composite_unbind), */ - .unbind = composite_unbind, - - .setup = composite_setup, - .disconnect = composite_disconnect, - - .suspend = composite_suspend, - .resume = composite_resume, - - .driver = { - .owner = THIS_MODULE, - }, -}; - -/** - * usb_composite_register() - register a composite driver - * @driver: the driver to register - * Context: single threaded during gadget setup - * - * This function is used to register drivers using the composite driver - * framework. The return value is zero, or a negative errno value. - * Those values normally come from the driver's @bind method, which does - * all the work of setting up the driver to match the hardware. - * - * On successful return, the gadget is ready to respond to requests from - * the host, unless one of its components invokes usb_gadget_disconnect() - * while it was binding. That would usually be done in order to wait for - * some userspace participation. - */ -int usb_composite_register(struct usb_composite_driver *driver) -{ - if (!driver || !driver->dev || !driver->bind || composite) - return -EINVAL; - - if (!driver->name) - driver->name = "composite"; - composite_driver.function = (char *) driver->name; - composite_driver.driver.name = driver->name; - composite = driver; - - return usb_gadget_register_driver(&composite_driver); -} - -/** - * usb_composite_unregister() - unregister a composite driver - * @driver: the driver to unregister - * - * This function is used to unregister drivers using the composite - * driver framework. - */ -void usb_composite_unregister(struct usb_composite_driver *driver) -{ - if (composite != driver) - return; - usb_gadget_unregister_driver(&composite_driver); -} - diff --git a/brick/kernel/d_usbdev.c b/brick/kernel/d_usbdev.c deleted file mode 100644 index 30d4847f..00000000 --- a/brick/kernel/d_usbdev.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * This UsbDev file is based on and inheritated from - * the original file (zero.c) and work done by David Brownell - * - * >> zero.c -- Gadget Zero, for USB development << - * - * >> Copyright (C) 2003-2008 David Brownell << - * >> Copyright (C) 2008 by Nokia Corporation << - * - */ - -/*! \page UsbdevModule USB device Module - * - * - *- \subpage UsbdevModuleResources - */ - - -#ifndef PCASM -#include -#endif - -#include "source/lms2012.h" -#include "source/am1808.h" - - -#define MODULE_NAME "usbdev_module" -#define DEVICE1_NAME USBDEV_DEVICE - - - -static int ModuleInit(void); -static void ModuleExit(void); - -#define __USE_POSIX - -#include -#include - -#include - - -#ifndef PCASM -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct fsg_common *fsg_common; - -#include "computil.c" // The composite framework used as utility file -#include <../drivers/usb/gadget/gadget_chips.h> -#include <../drivers/usb/gadget/usbstring.c> -#include <../drivers/usb/gadget/config.c> -#include <../drivers/usb/gadget/epautoconf.c> - -#include "f_mass_storage.c" - -/*-------------------------------------------------------------------------*/ - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ - -#include <../drivers/usb/gadget/g_zero.h> -#define MAX_EP_SIZE 1024 -#define MAX_FULLSPEED_EP_SIZE 64 -unsigned buflen = MAX_EP_SIZE ; -char usb_char_buffer_in[MAX_EP_SIZE]; -char usb_full_buffer_in[MAX_FULLSPEED_EP_SIZE]; -int usb_char_in_length = 0; -char usb_char_buffer_out[MAX_EP_SIZE]; -char usb_full_buffer_out[MAX_FULLSPEED_EP_SIZE]; -int usb_char_out_length = 0; - -#define SHM_LENGTH (sizeof(UsbSpeedDefault)) -#define NPAGES ((SHM_LENGTH + PAGE_SIZE - 1) / PAGE_SIZE) -static void *kmalloc_ptr; - -#include "usb_function.c" // Specific USB functionality - -/*-------------------------------------------------------------------------*/ - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("The LEGO Group"); -MODULE_DESCRIPTION(MODULE_NAME); -MODULE_SUPPORTED_DEVICE(DEVICE1_NAME); - -module_init(ModuleInit); -module_exit(ModuleExit); - -#else -// Keep Eclipse happy -#endif - -// USB main stuff - -#define DRIVER_VERSION "31jan2011->" - -#ifndef PCASM -module_param(buflen, uint, 0); -#else -// Keep Eclipse happy -#endif - -static int loopdefault = 0; -#ifndef PCASM -module_param(loopdefault, bool, S_IRUGO|S_IWUSR); -#else -// Keep Eclipse happy -#endif - -#define DRIVER_VENDOR_NUM 0x0694 // LEGO Group -#define DRIVER_PRODUCT_NUM 0x0005 // No. 5 in a row -#define DEFAULT_AUTORESUME 0 - -/* If the optional "autoresume" mode is enabled, it provides good - * functional coverage for the "USBCV" test harness from USB-IF. - * It's always set if OTG mode is enabled. - */ - -unsigned autoresume = DEFAULT_AUTORESUME; -module_param(autoresume, uint, S_IRUGO); - -#ifndef PCASM -MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); -#else -// Keep Eclipse happy -#endif - -/*-------------------------------------------------------------------------*/ - -static struct usb_device_descriptor device_desc = { - .bLength = sizeof device_desc, - .bDescriptorType = USB_DT_DEVICE, - - .bcdUSB = cpu_to_le16(0x0200), - .bDeviceClass = 0xEF, - .bDeviceSubClass = 2, - .bDeviceProtocol = 1, - - /*.bMaxPacketSize0 = f(hardware) */ - .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), - - .bNumConfigurations = 1, -}; - -#ifdef CONFIG_USB_OTG -struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; - -const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, - NULL, -}; -#endif - -/* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_SERIAL_IDX 2 - -static char manufacturer[] = "LEGO Group"; -static char serial[] = "123456789ABC "; -static char longname[] = "EV3 brick "; - -static struct usb_string strings_dev[3] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = longname, - [STRING_SERIAL_IDX].s = serial -}; - - -static struct usb_gadget_strings stringtab_dev = { - .language = 0x0409, /* en-us */ - .strings = strings_dev, -}; - -static struct usb_gadget_strings *dev_strings[] = { - &stringtab_dev, - NULL, -}; - -/*-------------------------------------------------------------------------*/ - -struct usb_request *alloc_ep_req(struct usb_ep *ep) -{ - struct usb_request *req; - - req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (req) { - req->length = buflen; - req->buf = kmalloc(buflen, GFP_ATOMIC); - if (!req->buf) { - usb_ep_free_request(ep, req); - req = NULL; - } - } - return req; -} - -void free_ep_req(struct usb_ep *ep, struct usb_request *req) -{ - kfree(req->buf); - usb_ep_free_request(ep, req); -} - -static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) -{ - int value; - - if (ep->driver_data) { - value = usb_ep_disable(ep); - if (value < 0) - DBG(cdev, "disable %s --> %d\n", - ep->name, value); - ep->driver_data = NULL; - } -} - -void disable_endpoints(struct usb_composite_dev *cdev, - struct usb_ep *in, struct usb_ep *out) -{ - disable_ep(cdev, in); - disable_ep(cdev, out); -} - -/*-------------------------------------------------------------------------*/ - -static struct timer_list autoresume_timer; - -static void zero_autoresume(unsigned long _c) -{ - struct usb_composite_dev *cdev = (void *)_c; - struct usb_gadget *g = cdev->gadget; - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("zero_autoresume\n\r"); - #endif - - /* unconfigured devices can't issue wakeups */ - if (!cdev->config) - return; - - /* Normally the host would be woken up for something - * more significant than just a timer firing; likely - * because of some direct user request. - */ - if (g->speed != USB_SPEED_UNKNOWN) { - int status = usb_gadget_wakeup(g); - INFO(cdev, "%s --> %d\n", __func__, status); - } -} - -static void zero_suspend(struct usb_composite_dev *cdev) -{ - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("zero_suspend\n\r"); - #endif - - if (cdev->gadget->speed == USB_SPEED_UNKNOWN) - return; - - if (autoresume) { - mod_timer(&autoresume_timer, jiffies + (HZ * autoresume)); - DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); - } else - DBG(cdev, "%s\n", __func__); -} - -static void zero_resume(struct usb_composite_dev *cdev) -{ - DBG(cdev, "%s\n", __func__); - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("zero_resume\n\r"); - #endif - - del_timer(&autoresume_timer); -} - -/*-------------------------------------------------------------------------*/ - -static int msg_bind(struct usb_composite_dev *cdev); -static void msg_bind2(struct usb_composite_dev *cdev); - -static int zero_bind(struct usb_composite_dev *cdev) -{ - int gcnum; - struct usb_gadget *gadget = cdev->gadget; - int id; - - /* Allocate string descriptor numbers ... note that string - * contents can be overridden by the composite_dev glue. - */ - id = usb_string_id(cdev); - if (id < 0) - return id; - - strings_dev[STRING_MANUFACTURER_IDX].id = id; - device_desc.iManufacturer = id; - - id = usb_string_id(cdev); - if (id < 0) - return id; - - - strings_dev[STRING_PRODUCT_IDX].id = id; - device_desc.iProduct = id; - - id = usb_string_id(cdev); - if (id < 0) - return id; - - - strings_dev[STRING_SERIAL_IDX].id = id; - device_desc.iSerialNumber = id; - - id = msg_bind(cdev); - if (id < 0) - return id; - - setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); - - rudolf_add(cdev, autoresume != 0); - - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); - else { - /* gadget zero is so simple (for now, no altsettings) that - * it SHOULD NOT have problems with bulk-capable hardware. - * so just warn about unrcognized controllers -- don't panic. - * - * things like configuration and altsetting numbering - * can need hardware-specific attention though. - */ - pr_warning("%s: controller '%s' not recognized\n", - longname, gadget->name); - device_desc.bcdDevice = cpu_to_le16(0x9999); - } - - msg_bind2(cdev); - - return 0; -} - -static int zero_unbind(struct usb_composite_dev *cdev) -{ - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("zero_unbind\n\r"); - #endif - - del_timer_sync(&autoresume_timer); - return 0; -} - -static struct usb_composite_driver zero_driver = { - .name = "zero", - .dev = &device_desc, - .strings = dev_strings, - .bind = zero_bind, - .unbind = zero_unbind, - .suspend = zero_suspend, - .resume = zero_resume, -}; - -static int dUsbInit(void) -{ - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("dUsbInit\n\r"); - #endif - - UsbSpeed.Speed = FULL_SPEED; // default to FULL_SPEED if not connected to a HIGH-SPEED - (*pUsbSpeed).Speed = FULL_SPEED; // HOST. If not connected to HIGH-SPEED we assume we're - // wanting (or at least doing) Daisy Chain - return usb_composite_register(&zero_driver); -} - -static void dUsbExit(void) -{ - usb_composite_unregister(&zero_driver); -} - -// DEVICE1 char device stuff ******************************************************************** - -static ssize_t Device1Write(struct file *File,const char *Buffer,size_t Count,loff_t *Data) -{ - // Write data for the HOST to poll - Stuff sent to the HOST - - int BytesWritten = 0; - - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("Device1Write - usb_char_in_length = %d\n", usb_char_in_length); - #endif - - if (usb_char_in_length == 0) // ready for more - { // else wait in USER layer - BytesWritten = Count; - copy_from_user(usb_char_buffer_in, Buffer, BytesWritten); - usb_char_in_length = BytesWritten; - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("WR = %d, %d -- ", usb_char_buffer_in[2], usb_char_buffer_in[3]); - #endif - - if(USB_DATA_PENDING == input_state) - { - // Already we've a failed tx (HOST part starwing?? - - input_state = USB_DATA_READY; - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("DATA_PENDING SECOND time and reset!! in Device1Write\n\r"); - #endif - } - - if(USB_DATA_READY == input_state) - { - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("USB_DATA_READY in Device1Write\n\r"); - #endif - - input_state = USB_DATA_BUSY; - write_data_to_the_host(save_in_ep, save_in_req); - usb_req_arm(save_in_ep, save_in_req); // new request - } - else - { - input_state = USB_DATA_PENDING; - - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("DATA_PENDING in Device1Write\n\r"); - #endif - } - } - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("usbdev %d written\n\r", BytesWritten); - #endif - - return (BytesWritten); // Zero means USB was not ready yet -} - -static ssize_t Device1Read(struct file *File,char *Buffer,size_t Count,loff_t *Offset) -{ - // Read the bits'n'bytes from the HOST - int BytesRead = 0; - - if (usb_char_out_length > 0) // Something to look at - { - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("Some bytes to READ?\n\r"); - #endif - - copy_to_user(Buffer, usb_char_buffer_out, Count); - BytesRead = usb_char_out_length; - usb_char_out_length = 0; - } - return (BytesRead); -} - -static int Device1Mmap(struct file *filp, struct vm_area_struct *vma) -{ - int ret; - - ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys((void*)((unsigned long)pUsbSpeed)) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,PAGE_SHARED); - - if (ret != 0) - { - ret = -EAGAIN; - } - - return (ret); -} - -#define FEED_DATA _IOC(_IOC_WRITE, 't', 108, 1024) - -static int Device1Ioctl(struct inode *pNode, struct file *File, unsigned int Request, unsigned long Pointer) -{ - if (Request != FEED_DATA) - return -EINVAL; - - copy_from_user(usb_char_buffer_out,(void*)Pointer,1024); - usb_char_out_length = 1024; - - return 0; -} - -static const struct file_operations Device1Entries = -{ - .owner = THIS_MODULE, - .read = Device1Read, - .write = Device1Write, - .mmap = Device1Mmap, - .ioctl = Device1Ioctl -}; - - -static struct miscdevice Device1 = -{ - MISC_DYNAMIC_MINOR, - DEVICE1_NAME, - &Device1Entries -}; - - -static int Device1Init(void) -{ - int Result = -1; - UWORD *pTemp; - int i; - - Result = misc_register(&Device1); - if (Result) - { - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk(" %s device register failed\n",DEVICE1_NAME); - #endif - } - else - { - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk(" %s device register OK\n",DEVICE1_NAME); - #endif - - // allocate kernel shared memory for DaisyChain Speed info - - if ((kmalloc_ptr = kmalloc((NPAGES + 2) * PAGE_SIZE, GFP_KERNEL)) != NULL) - { - - pTemp = (UWORD*)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK); - - for (i = 0; i < NPAGES * PAGE_SIZE; i += PAGE_SIZE) - { - SetPageReserved(virt_to_page(((unsigned long)pTemp) + i)); - } - - pUsbSpeed = (USB_SPEED*)pTemp; - } - - dUsbInit(); - } - - return (Result); -} - -static void Device1Exit(void) -{ - int i; - UWORD *pTemp = (UWORD*)pUsbSpeed; - - dUsbExit(); - - pUsbSpeed = &UsbSpeedDefault; - - for (i = 0; i < NPAGES * PAGE_SIZE; i+= PAGE_SIZE) - { - ClearPageReserved(virt_to_page(((unsigned long)pTemp) + i)); - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk(" %s memory page %d unmapped\n",DEVICE1_NAME,i); - #endif - } - - kfree(kmalloc_ptr); - - misc_deregister(&Device1); - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk(" %s device unregistered\n",DEVICE1_NAME); - #endif -} - - -// MODULE ********************************************************************* - -char *HostStr; // Used for HostName - or NOT used at all -char *SerialStr; // Used for Serial number (I.e. BT number) - -module_param (HostStr, charp, 0); -module_param (SerialStr, charp, 0); - -static int ModuleInit(void) -{ - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("%s Module init started\r\n",MODULE_NAME); - #endif - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("This is DEFAULT NAME: %s\n\r", longname); - #endif - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("\n\rThis is the HostStr: %s\n\r", HostStr); - #endif - - strcpy(longname, HostStr); - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("\n\rThis is the INSMODed NAME: %s\n\r", longname); - #endif - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("\n\rThis is the DEFAULT SerialNumber: %s\n\r", serial); - #endif - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("\n\rThis is the SerialStr: %s\n\r", SerialStr); - #endif - - strcpy(serial, SerialStr); - - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("\n\rThis is the INSMODed SerialNumber (BT mac): %s\n\r", serial); - #endif - - Device1Init(); - - return (0); -} - -static void ModuleExit(void) -{ - //#define DEBUG - #undef DEBUG - #ifdef DEBUG - printk("%s exit started\n",MODULE_NAME); - #endif - - Device1Exit(); - -} - - - - -// MSG - - -/****************************** Configurations ******************************/ - -static struct fsg_module_parameters fsg_mod_data = { - .stall = 1 -}; -FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); - -/****************************** Gadget Bind ******************************/ - - -static void msg_bind2(struct usb_composite_dev *cdev) -{ - fsg_common_put(fsg_common); -} - -static int msg_bind(struct usb_composite_dev *cdev) -{ - /* set up mass storage function */ - fsg_common = fsg_common_from_params(0, cdev, &fsg_mod_data); - if (IS_ERR(fsg_common)) { - return PTR_ERR(fsg_common); - } - return 0; -} - - -static int msg_config(struct usb_configuration *c) { - return fsg_add(c->cdev, c, fsg_common); -} diff --git a/brick/kernel/f_mass_storage.c b/brick/kernel/f_mass_storage.c deleted file mode 100644 index 2c6d4b05..00000000 --- a/brick/kernel/f_mass_storage.c +++ /dev/null @@ -1,3165 +0,0 @@ -/* - * f_mass_storage.c -- Mass Storage USB Composite Function - * - * Copyright (C) 2003-2008 Alan Stern - * Copyright (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any - * later version. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* - * The Mass Storage Function acts as a USB Mass Storage device, - * appearing to the host as a disk drive or as a CD-ROM drive. In - * addition to providing an example of a genuinely useful composite - * function for a USB device, it also illustrates a technique of - * double-buffering for increased throughput. - * - * Function supports multiple logical units (LUNs). Backing storage - * for each LUN is provided by a regular file or a block device. - * Access for each LUN can be limited to read-only. Moreover, the - * function can indicate that LUN is removable and/or CD-ROM. (The - * later implies read-only access.) - * - * MSF is configured by specifying a fsg_config structure. It has the - * following fields: - * - * nluns Number of LUNs function have (anywhere from 1 - * to FSG_MAX_LUNS which is 8). - * luns An array of LUN configuration values. This - * should be filled for each LUN that - * function will include (ie. for "nluns" - * LUNs). Each element of the array has - * the following fields: - * ->filename The path to the backing file for the LUN. - * Required if LUN is not marked as - * removable. - * ->ro Flag specifying access to the LUN shall be - * read-only. This is implied if CD-ROM - * emulation is enabled as well as when - * it was impossible to open "filename" - * in R/W mode. - * ->removable Flag specifying that LUN shall be indicated as - * being removable. - * ->cdrom Flag specifying that LUN shall be reported as - * being a CD-ROM. - * - * lun_name_format A printf-like format for names of the LUN - * devices. This determines how the - * directory in sysfs will be named. - * Unless you are using several MSFs in - * a single gadget (as opposed to single - * MSF in many configurations) you may - * leave it as NULL (in which case - * "lun%d" will be used). In the format - * you can use "%d" to index LUNs for - * MSF's with more than one LUN. (Beware - * that there is only one integer given - * as an argument for the format and - * specifying invalid format may cause - * unspecified behaviour.) - * thread_name Name of the kernel thread process used by the - * MSF. You can safely set it to NULL - * (in which case default "file-storage" - * will be used). - * - * vendor_name - * product_name - * release Information used as a reply to INQUIRY - * request. To use default set to NULL, - * NULL, 0xffff respectively. The first - * field should be 8 and the second 16 - * characters or less. - * - * can_stall Set to permit function to halt bulk endpoints. - * Disabled on some USB devices known not - * to work correctly. You should set it - * to true. - * - * If "removable" is not set for a LUN then a backing file must be - * specified. If it is set, then NULL filename means the LUN's medium - * is not loaded (an empty string as "filename" in the fsg_config - * structure causes error). The CD-ROM emulation includes a single - * data track and no audio tracks; hence there need be only one - * backing file per LUN. Note also that the CD-ROM block length is - * set to 512 rather than the more common value 2048. - * - * - * MSF includes support for module parameters. If gadget using it - * decides to use it, the following module parameters will be - * available: - * - * file=filename[,filename...] - * Names of the files or block devices used for - * backing storage. - * ro=b[,b...] Default false, boolean for read-only access. - * removable=b[,b...] - * Default true, boolean for removable media. - * cdrom=b[,b...] Default false, boolean for whether to emulate - * a CD-ROM drive. - * luns=N Default N = number of filenames, number of - * LUNs to support. - * stall Default determined according to the type of - * USB device controller (usually true), - * boolean to permit the driver to halt - * bulk endpoints. - * - * The module parameters may be prefixed with some string. You need - * to consult gadget's documentation or source to verify whether it is - * using those module parameters and if it does what are the prefixes - * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is - * the prefix). - * - * - * Requirements are modest; only a bulk-in and a bulk-out endpoint are - * needed. The memory requirement amounts to two 16K buffers, size - * configurable by a parameter. Support is included for both - * full-speed and high-speed operation. - * - * Note that the driver is slightly non-portable in that it assumes a - * single memory/DMA buffer will be useable for bulk-in, bulk-out, and - * interrupt-in endpoints. With most device controllers this isn't an - * issue, but there may be some with hardware restrictions that prevent - * a buffer from being used by more than one endpoint. - * - * - * The pathnames of the backing files and the ro settings are - * available in the attribute files "file" and "ro" in the lun (or - * to be more precise in a directory which name comes from - * "lun_name_format" option!) subdirectory of the gadget's sysfs - * directory. If the "removable" option is set, writing to these - * files will simulate ejecting/loading the medium (writing an empty - * line means eject) and adjusting a write-enable tab. Changes to the - * ro setting are not allowed when the medium is loaded or if CD-ROM - * emulation is being used. - * - * - * This function is heavily based on "File-backed Storage Gadget" by - * Alan Stern which in turn is heavily based on "Gadget Zero" by David - * Brownell. The driver's SCSI command interface was based on the - * "Information technology - Small Computer System Interface - 2" - * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, - * available at . - * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which - * was based on the "Universal Serial Bus Mass Storage Class UFI - * Command Specification" document, Revision 1.0, December 14, 1998, - * available at - * . - */ - - -/* - * Driver Design - * - * The MSF is fairly straightforward. There is a main kernel - * thread that handles most of the work. Interrupt routines field - * callbacks from the controller driver: bulk- and interrupt-request - * completion notifications, endpoint-0 events, and disconnect events. - * Completion events are passed to the main thread by wakeup calls. Many - * ep0 requests are handled at interrupt time, but SetInterface, - * SetConfiguration, and device reset requests are forwarded to the - * thread in the form of "exceptions" using SIGUSR1 signals (since they - * should interrupt any ongoing file I/O operations). - * - * The thread's main routine implements the standard command/data/status - * parts of a SCSI interaction. It and its subroutines are full of tests - * for pending signals/exceptions -- all this polling is necessary since - * the kernel has no setjmp/longjmp equivalents. (Maybe this is an - * indication that the driver really wants to be running in userspace.) - * An important point is that so long as the thread is alive it keeps an - * open reference to the backing file. This will prevent unmounting - * the backing file's underlying filesystem and could cause problems - * during system shutdown, for example. To prevent such problems, the - * thread catches INT, TERM, and KILL signals and converts them into - * an EXIT exception. - * - * In normal operation the main thread is started during the gadget's - * fsg_bind() callback and stopped during fsg_unbind(). But it can - * also exit when it receives a signal, and there's no point leaving - * the gadget running when the thread is dead. At of this moment, MSF - * provides no way to deregister the gadget when thread dies -- maybe - * a callback functions is needed. - * - * To provide maximum throughput, the driver uses a circular pipeline of - * buffer heads (struct fsg_buffhd). In principle the pipeline can be - * arbitrarily long; in practice the benefits don't justify having more - * than 2 stages (i.e., double buffering). But it helps to think of the - * pipeline as being a long one. Each buffer head contains a bulk-in and - * a bulk-out request pointer (since the buffer can be used for both - * output and input -- directions always are given from the host's - * point of view) as well as a pointer to the buffer and various state - * variables. - * - * Use of the pipeline follows a simple protocol. There is a variable - * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. - * At any time that buffer head may still be in use from an earlier - * request, so each buffer head has a state variable indicating whether - * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the - * buffer head to be EMPTY, filling the buffer either by file I/O or by - * USB I/O (during which the buffer head is BUSY), and marking the buffer - * head FULL when the I/O is complete. Then the buffer will be emptied - * (again possibly by USB I/O, during which it is marked BUSY) and - * finally marked EMPTY again (possibly by a completion routine). - * - * A module parameter tells the driver to avoid stalling the bulk - * endpoints wherever the transport specification allows. This is - * necessary for some UDCs like the SuperH, which cannot reliably clear a - * halt on a bulk endpoint. However, under certain circumstances the - * Bulk-only specification requires a stall. In such cases the driver - * will halt the endpoint and set a flag indicating that it should clear - * the halt in software during the next device reset. Hopefully this - * will permit everything to work correctly. Furthermore, although the - * specification allows the bulk-out endpoint to halt when the host sends - * too much data, implementing this would cause an unavoidable race. - * The driver will always use the "no-stall" approach for OUT transfers. - * - * One subtle point concerns sending status-stage responses for ep0 - * requests. Some of these requests, such as device reset, can involve - * interrupting an ongoing file I/O operation, which might take an - * arbitrarily long time. During that delay the host might give up on - * the original ep0 request and issue a new one. When that happens the - * driver should not notify the host about completion of the original - * request, as the host will no longer be waiting for it. So the driver - * assigns to each ep0 request a unique tag, and it keeps track of the - * tag value of the request associated with a long-running exception - * (device-reset, interface-change, or configuration-change). When the - * exception handler is finished, the status-stage response is submitted - * only if the current ep0 request tag is equal to the exception request - * tag. Thus only the most recently received ep0 request will get a - * status-stage response. - * - * Warning: This driver source file is too long. It ought to be split up - * into a header file plus about 3 separate .c files, to handle the details - * of the Gadget, USB Mass Storage, and SCSI protocols. - */ - - -/* #define VERBOSE_DEBUG */ -/* #define DUMP_MSGS */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gadget_chips.h" - - - -/*------------------------------------------------------------------------*/ - -#define FSG_DRIVER_DESC "Mass Storage Function" -#define FSG_DRIVER_VERSION "2009/09/11" - -static const char fsg_string_interface[] = "Mass Storage"; - - -#define FSG_NO_INTR_EP 1 -#define FSG_BUFFHD_STATIC_BUFFER 1 -#define FSG_NO_DEVICE_STRINGS 1 -#define FSG_NO_OTG 1 -#define FSG_NO_INTR_EP 1 - -#include "storage_common.c" - - -/*-------------------------------------------------------------------------*/ - -struct fsg_dev; - - -/* Data shared by all the FSG instances. */ -struct fsg_common { - struct usb_gadget *gadget; - struct fsg_dev *fsg; - struct fsg_dev *prev_fsg; - - /* filesem protects: backing files in use */ - struct rw_semaphore filesem; - - /* lock protects: state, all the req_busy's */ - spinlock_t lock; - - struct usb_ep *ep0; /* Copy of gadget->ep0 */ - struct usb_request *ep0req; /* Copy of cdev->req */ - unsigned int ep0_req_tag; - const char *ep0req_name; - - struct fsg_buffhd *next_buffhd_to_fill; - struct fsg_buffhd *next_buffhd_to_drain; - struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; - - int cmnd_size; - u8 cmnd[MAX_COMMAND_SIZE]; - - unsigned int nluns; - unsigned int lun; - struct fsg_lun *luns; - struct fsg_lun *curlun; - - unsigned int bulk_out_maxpacket; - enum fsg_state state; /* For exception handling */ - unsigned int exception_req_tag; - - u8 config, new_config; - enum data_direction data_dir; - u32 data_size; - u32 data_size_from_cmnd; - u32 tag; - u32 residue; - u32 usb_amount_left; - - unsigned int can_stall:1; - unsigned int free_storage_on_release:1; - unsigned int phase_error:1; - unsigned int short_packet_received:1; - unsigned int bad_lun_okay:1; - unsigned int running:1; - - int thread_wakeup_needed; - struct completion thread_notifier; - struct task_struct *thread_task; - - /* Callback function to call when thread exits. */ - void (*thread_exits)(struct fsg_common *common); - /* Gadget's private data. */ - void *private_data; - - /* Vendor (8 chars), product (16 chars), release (4 - * hexadecimal digits) and NUL byte */ - char inquiry_string[8 + 16 + 4 + 1]; - - struct kref ref; -}; - - -struct fsg_config { - unsigned nluns; - struct fsg_lun_config { - const char *filename; - char ro; - char removable; - char cdrom; - } luns[FSG_MAX_LUNS]; - - const char *lun_name_format; - const char *thread_name; - - /* Callback function to call when thread exits. */ - void (*thread_exits)(struct fsg_common *common); - /* Gadget's private data. */ - void *private_data; - - const char *vendor_name; /* 8 characters or less */ - const char *product_name; /* 16 characters or less */ - u16 release; - - char can_stall; -}; - - -struct fsg_dev { - struct usb_function function; - struct usb_gadget *gadget; /* Copy of cdev->gadget */ - struct fsg_common *common; - - u16 interface_number; - - unsigned int bulk_in_enabled:1; - unsigned int bulk_out_enabled:1; - - unsigned long atomic_bitflags; -#define IGNORE_BULK_OUT 0 - - struct usb_ep *bulk_in; - struct usb_ep *bulk_out; -}; - - -static inline int __fsg_is_set(struct fsg_common *common, - const char *func, unsigned line) -{ - if (common->fsg) - return 1; - ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); - return 0; -} - -#define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) - - -static inline struct fsg_dev *fsg_from_func(struct usb_function *f) -{ - return container_of(f, struct fsg_dev, function); -} - - -typedef void (*fsg_routine_t)(struct fsg_dev *); - -static int exception_in_progress(struct fsg_common *common) -{ - return common->state > FSG_STATE_IDLE; -} - -/* Make bulk-out requests be divisible by the maxpacket size */ -static void set_bulk_out_req_length(struct fsg_common *common, - struct fsg_buffhd *bh, unsigned int length) -{ - unsigned int rem; - - bh->bulk_out_intended_length = length; - rem = length % common->bulk_out_maxpacket; - if (rem > 0) - length += common->bulk_out_maxpacket - rem; - bh->outreq->length = length; -} - -/*-------------------------------------------------------------------------*/ - -static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) -{ - const char *name; - - if (ep == fsg->bulk_in) - name = "bulk-in"; - else if (ep == fsg->bulk_out) - name = "bulk-out"; - else - name = ep->name; - DBG(fsg, "%s set halt\n", name); - return usb_ep_set_halt(ep); -} - - -/*-------------------------------------------------------------------------*/ - -/* These routines may be called in process context or in_irq */ - -/* Caller must hold fsg->lock */ -static void wakeup_thread(struct fsg_common *common) -{ - /* Tell the main thread that something has happened */ - common->thread_wakeup_needed = 1; - if (common->thread_task) - wake_up_process(common->thread_task); -} - - -static void raise_exception(struct fsg_common *common, enum fsg_state new_state) -{ - unsigned long flags; - - /* Do nothing if a higher-priority exception is already in progress. - * If a lower-or-equal priority exception is in progress, preempt it - * and notify the main thread by sending it a signal. */ - spin_lock_irqsave(&common->lock, flags); - if (common->state <= new_state) { - common->exception_req_tag = common->ep0_req_tag; - common->state = new_state; - if (common->thread_task) - send_sig_info(SIGUSR1, SEND_SIG_FORCED, - common->thread_task); - } - spin_unlock_irqrestore(&common->lock, flags); -} - - -/*-------------------------------------------------------------------------*/ - -static int ep0_queue(struct fsg_common *common) -{ - int rc; - - rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); - common->ep0->driver_data = common; - if (rc != 0 && rc != -ESHUTDOWN) { - /* We can't do much more than wait for a reset */ - WARNING(common, "error in submission: %s --> %d\n", - common->ep0->name, rc); - } - return rc; -} - -/*-------------------------------------------------------------------------*/ - -/* Bulk and interrupt endpoint completion handlers. - * These always run in_irq. */ - -static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct fsg_common *common = ep->driver_data; - struct fsg_buffhd *bh = req->context; - - if (req->status || req->actual != req->length) - DBG(common, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, req->length); - if (req->status == -ECONNRESET) /* Request was cancelled */ - usb_ep_fifo_flush(ep); - - /* Hold the lock while we update the request and buffer states */ - smp_wmb(); - spin_lock(&common->lock); - bh->inreq_busy = 0; - bh->state = BUF_STATE_EMPTY; - wakeup_thread(common); - spin_unlock(&common->lock); -} - -static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct fsg_common *common = ep->driver_data; - struct fsg_buffhd *bh = req->context; - - dump_msg(common, "bulk-out", req->buf, req->actual); - if (req->status || req->actual != bh->bulk_out_intended_length) - DBG(common, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, - bh->bulk_out_intended_length); - if (req->status == -ECONNRESET) /* Request was cancelled */ - usb_ep_fifo_flush(ep); - - /* Hold the lock while we update the request and buffer states */ - smp_wmb(); - spin_lock(&common->lock); - bh->outreq_busy = 0; - bh->state = BUF_STATE_FULL; - wakeup_thread(common); - spin_unlock(&common->lock); -} - - -/*-------------------------------------------------------------------------*/ - -/* Ep0 class-specific handlers. These always run in_irq. */ - -static int fsg_setup(struct usb_function *f, - const struct usb_ctrlrequest *ctrl) -{ - struct fsg_dev *fsg = fsg_from_func(f); - struct usb_request *req = fsg->common->ep0req; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - - if (!fsg->common->config) - return -EOPNOTSUPP; - - switch (ctrl->bRequest) { - - case USB_BULK_RESET_REQUEST: - if (ctrl->bRequestType != - (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) - break; - if (w_index != fsg->interface_number || w_value != 0) - return -EDOM; - - /* Raise an exception to stop the current operation - * and reinitialize our state. */ - DBG(fsg, "bulk reset request\n"); - raise_exception(fsg->common, FSG_STATE_RESET); - return DELAYED_STATUS; - - case USB_BULK_GET_MAX_LUN_REQUEST: - if (ctrl->bRequestType != - (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) - break; - if (w_index != fsg->interface_number || w_value != 0) - return -EDOM; - VDBG(fsg, "get max LUN\n"); - *(u8 *) req->buf = fsg->common->nluns - 1; - return 1; - } - - VDBG(fsg, - "unknown class-specific control req " - "%02x.%02x v%04x i%04x l%u\n", - ctrl->bRequestType, ctrl->bRequest, - le16_to_cpu(ctrl->wValue), w_index, w_length); - return -EOPNOTSUPP; -} - - -/*-------------------------------------------------------------------------*/ - -/* All the following routines run in process context */ - - -/* Use this for bulk or interrupt transfers, not ep0 */ -static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, - struct usb_request *req, int *pbusy, - enum fsg_buffer_state *state) -{ - int rc; - - if (ep == fsg->bulk_in) - dump_msg(fsg, "bulk-in", req->buf, req->length); - - spin_lock_irq(&fsg->common->lock); - *pbusy = 1; - *state = BUF_STATE_BUSY; - spin_unlock_irq(&fsg->common->lock); - rc = usb_ep_queue(ep, req, GFP_KERNEL); - if (rc != 0) { - *pbusy = 0; - *state = BUF_STATE_EMPTY; - - /* We can't do much more than wait for a reset */ - - /* Note: currently the net2280 driver fails zero-length - * submissions if DMA is enabled. */ - if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && - req->length == 0)) - WARNING(fsg, "error in submission: %s --> %d\n", - ep->name, rc); - } -} - -#define START_TRANSFER_OR(common, ep_name, req, pbusy, state) \ - if (fsg_is_set(common)) \ - start_transfer((common)->fsg, (common)->fsg->ep_name, \ - req, pbusy, state); \ - else - -#define START_TRANSFER(common, ep_name, req, pbusy, state) \ - START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0 - - - -static int sleep_thread(struct fsg_common *common) -{ - int rc = 0; - - /* Wait until a signal arrives or we are woken up */ - for (;;) { - try_to_freeze(); - set_current_state(TASK_INTERRUPTIBLE); - if (signal_pending(current)) { - rc = -EINTR; - break; - } - if (common->thread_wakeup_needed) - break; - schedule(); - } - __set_current_state(TASK_RUNNING); - common->thread_wakeup_needed = 0; - return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static int do_read(struct fsg_common *common) -{ - struct fsg_lun *curlun = common->curlun; - u32 lba; - struct fsg_buffhd *bh; - int rc; - u32 amount_left; - loff_t file_offset, file_offset_tmp; - unsigned int amount; - // partial_page handling causes hangs - // same thing in do_write() --mmoskal - //unsigned int partial_page; - ssize_t nread; - - /* Get the starting Logical Block Address and check that it's - * not too big */ - if (common->cmnd[0] == SC_READ_6) - lba = get_unaligned_be24(&common->cmnd[1]); - else { - lba = get_unaligned_be32(&common->cmnd[2]); - - /* We allow DPO (Disable Page Out = don't save data in the - * cache) and FUA (Force Unit Access = don't read from the - * cache), but we don't implement them. */ - if ((common->cmnd[1] & ~0x18) != 0) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - } - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - file_offset = ((loff_t) lba) << 9; - - /* Carry out the file reads */ - amount_left = common->data_size_from_cmnd; - - LDBG(curlun, "Uread off=%d cnt=%d\n", (int)lba, amount_left); - - if (unlikely(amount_left == 0)) - return -EIO; /* No default reply */ - - for (;;) { - - /* Figure out how much we need to read: - * Try to read the remaining amount. - * But don't read more than the buffer size. - * And don't try to read past the end of the file. - * Finally, if we're not at a page boundary, don't read past - * the next page. - * If this means reading 0 then we were asked to read past - * the end of file. */ - amount = min(amount_left, FSG_BUFLEN); - amount = min((loff_t) amount, - curlun->file_length - file_offset); - /* - partial_page = file_offset & (PAGE_CACHE_SIZE - 1); - if (partial_page > 0) - amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - - partial_page); - */ - /* Wait for the next buffer to become available */ - bh = common->next_buffhd_to_fill; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - /* If we were asked to read past the end of file, - * end with an empty buffer. */ - if (amount == 0) { - curlun->sense_data = - SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - curlun->sense_data_info = file_offset >> 9; - curlun->info_valid = 1; - bh->inreq->length = 0; - bh->state = BUF_STATE_FULL; - break; - } - - /* Perform the read */ - file_offset_tmp = file_offset; - nread = vfs_read(curlun->filp, - (char __user *) bh->buf, - amount, &file_offset_tmp); - VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nread); - if (signal_pending(current)) - return -EINTR; - - if (nread < 0) { - LDBG(curlun, "error in file read: %d\n", - (int) nread); - nread = 0; - } else if (nread < amount) { - LDBG(curlun, "partial file read: %d/%u\n", - (int) nread, amount); - nread -= (nread & 511); /* Round down to a block */ - } - file_offset += nread; - amount_left -= nread; - common->residue -= nread; - bh->inreq->length = nread; - bh->state = BUF_STATE_FULL; - - /* If an error occurred, report it and its position */ - if (nread < amount) { - curlun->sense_data = SS_UNRECOVERED_READ_ERROR; - curlun->sense_data_info = file_offset >> 9; - curlun->info_valid = 1; - break; - } - - if (amount_left == 0) - break; /* No more left to read */ - - /* Send this buffer and go read some more */ - bh->inreq->zero = 0; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - return -EIO; - common->next_buffhd_to_fill = bh->next; - } - - return -EIO; /* No default reply */ -} - - -/*-------------------------------------------------------------------------*/ - -static int do_write(struct fsg_common *common) -{ - struct fsg_lun *curlun = common->curlun; - u32 lba; - struct fsg_buffhd *bh; - int get_some_more; - u32 amount_left_to_req, amount_left_to_write; - loff_t usb_offset, file_offset, file_offset_tmp; - unsigned int amount; - //unsigned int partial_page; - ssize_t nwritten; - int rc; - - if (curlun->ro) { - curlun->sense_data = SS_WRITE_PROTECTED; - return -EINVAL; - } - spin_lock(&curlun->filp->f_lock); - curlun->filp->f_flags |= O_SYNC; /* Default is to wait */ - spin_unlock(&curlun->filp->f_lock); - - /* Get the starting Logical Block Address and check that it's - * not too big */ - if (common->cmnd[0] == SC_WRITE_6) - lba = get_unaligned_be24(&common->cmnd[1]); - else { - lba = get_unaligned_be32(&common->cmnd[2]); - - /* We allow DPO (Disable Page Out = don't save data in the - * cache) and FUA (Force Unit Access = write directly to the - * medium). We don't implement DPO; we implement FUA by - * performing synchronous output. */ - if (common->cmnd[1] & ~0x18) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - if (common->cmnd[1] & 0x08) { /* FUA */ - spin_lock(&curlun->filp->f_lock); - curlun->filp->f_flags |= O_SYNC; - spin_unlock(&curlun->filp->f_lock); - } - } - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - - /* Carry out the file writes */ - get_some_more = 1; - file_offset = usb_offset = ((loff_t) lba) << 9; - amount_left_to_req = common->data_size_from_cmnd; - amount_left_to_write = common->data_size_from_cmnd; - - LDBG(curlun, "Uwrite off=%d cnt=%d\n", (int)lba, amount_left_to_req); - - while (amount_left_to_write > 0) { - - /* Queue a request for more data from the host */ - bh = common->next_buffhd_to_fill; - if (bh->state == BUF_STATE_EMPTY && get_some_more) { - - /* Figure out how much we want to get: - * Try to get the remaining amount. - * But don't get more than the buffer size. - * And don't try to go past the end of the file. - * If we're not at a page boundary, - * don't go past the next page. - * If this means getting 0, then we were asked - * to write past the end of file. - * Finally, round down to a block boundary. */ - amount = min(amount_left_to_req, FSG_BUFLEN); - amount = min((loff_t) amount, curlun->file_length - - usb_offset); - /* - partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); - if (partial_page > 0) - amount = min(amount, - (unsigned int) PAGE_CACHE_SIZE - partial_page); - */ - - if (amount == 0) { - get_some_more = 0; - curlun->sense_data = - SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - curlun->sense_data_info = usb_offset >> 9; - curlun->info_valid = 1; - continue; - } - amount -= (amount & 511); - if (amount == 0) { - - /* Why were we were asked to transfer a - * partial block? */ - get_some_more = 0; - continue; - } - - /* Get the next buffer */ - usb_offset += amount; - common->usb_amount_left -= amount; - amount_left_to_req -= amount; - if (amount_left_to_req == 0) - get_some_more = 0; - - /* amount is always divisible by 512, hence by - * the bulk-out maxpacket size */ - bh->outreq->length = amount; - bh->bulk_out_intended_length = amount; - bh->outreq->short_not_ok = 1; - START_TRANSFER_OR(common, bulk_out, bh->outreq, - &bh->outreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - return -EIO; - common->next_buffhd_to_fill = bh->next; - continue; - } - - /* Write the received data to the backing file */ - bh = common->next_buffhd_to_drain; - if (bh->state == BUF_STATE_EMPTY && !get_some_more) - break; /* We stopped early */ - if (bh->state == BUF_STATE_FULL) { - smp_rmb(); - common->next_buffhd_to_drain = bh->next; - bh->state = BUF_STATE_EMPTY; - - /* Did something go wrong with the transfer? */ - if (bh->outreq->status != 0) { - curlun->sense_data = SS_COMMUNICATION_FAILURE; - curlun->sense_data_info = file_offset >> 9; - curlun->info_valid = 1; - break; - } - - amount = bh->outreq->actual; - if (curlun->file_length - file_offset < amount) { - LERROR(curlun, - "write %u @ %llu beyond end %llu\n", - amount, (unsigned long long) file_offset, - (unsigned long long) curlun->file_length); - amount = curlun->file_length - file_offset; - } - - /* Perform the write */ - file_offset_tmp = file_offset; - nwritten = vfs_write(curlun->filp, - (char __user *) bh->buf, - amount, &file_offset_tmp); - VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nwritten); - if (signal_pending(current)) - return -EINTR; /* Interrupted! */ - - if (nwritten < 0) { - LDBG(curlun, "error in file write: %d\n", - (int) nwritten); - nwritten = 0; - } else if (nwritten < amount) { - LDBG(curlun, "partial file write: %d/%u\n", - (int) nwritten, amount); - nwritten -= (nwritten & 511); - /* Round down to a block */ - } - file_offset += nwritten; - amount_left_to_write -= nwritten; - common->residue -= nwritten; - - /* If an error occurred, report it and its position */ - if (nwritten < amount) { - curlun->sense_data = SS_WRITE_ERROR; - curlun->sense_data_info = file_offset >> 9; - curlun->info_valid = 1; - break; - } - - /* Did the host decide to stop early? */ - if (bh->outreq->actual != bh->outreq->length) { - common->short_packet_received = 1; - break; - } - continue; - } - - /* Wait for something to happen */ - rc = sleep_thread(common); - if (rc) - return rc; - } - - return -EIO; /* No default reply */ -} - - -/*-------------------------------------------------------------------------*/ - -static int do_synchronize_cache(struct fsg_common *common) -{ - struct fsg_lun *curlun = common->curlun; - int rc; - - /* We ignore the requested LBA and write out all file's - * dirty data buffers. */ - rc = fsg_lun_fsync_sub(curlun); - if (rc) - curlun->sense_data = SS_WRITE_ERROR; - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -static void invalidate_sub(struct fsg_lun *curlun) -{ - struct file *filp = curlun->filp; - struct inode *inode = filp->f_path.dentry->d_inode; - unsigned long rc; - - rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); - VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc); -} - -static int do_verify(struct fsg_common *common) -{ - struct fsg_lun *curlun = common->curlun; - u32 lba; - u32 verification_length; - struct fsg_buffhd *bh = common->next_buffhd_to_fill; - loff_t file_offset, file_offset_tmp; - u32 amount_left; - unsigned int amount; - ssize_t nread; - - /* Get the starting Logical Block Address and check that it's - * not too big */ - lba = get_unaligned_be32(&common->cmnd[2]); - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - - /* We allow DPO (Disable Page Out = don't save data in the - * cache) but we don't implement it. */ - if (common->cmnd[1] & ~0x10) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - verification_length = get_unaligned_be16(&common->cmnd[7]); - if (unlikely(verification_length == 0)) - return -EIO; /* No default reply */ - - /* Prepare to carry out the file verify */ - amount_left = verification_length << 9; - file_offset = ((loff_t) lba) << 9; - - /* Write out all the dirty buffers before invalidating them */ - fsg_lun_fsync_sub(curlun); - if (signal_pending(current)) - return -EINTR; - - invalidate_sub(curlun); - if (signal_pending(current)) - return -EINTR; - - /* Just try to read the requested blocks */ - while (amount_left > 0) { - - /* Figure out how much we need to read: - * Try to read the remaining amount, but not more than - * the buffer size. - * And don't try to read past the end of the file. - * If this means reading 0 then we were asked to read - * past the end of file. */ - amount = min(amount_left, FSG_BUFLEN); - amount = min((loff_t) amount, - curlun->file_length - file_offset); - if (amount == 0) { - curlun->sense_data = - SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - curlun->sense_data_info = file_offset >> 9; - curlun->info_valid = 1; - break; - } - - /* Perform the read */ - file_offset_tmp = file_offset; - nread = vfs_read(curlun->filp, - (char __user *) bh->buf, - amount, &file_offset_tmp); - VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, - (unsigned long long) file_offset, - (int) nread); - if (signal_pending(current)) - return -EINTR; - - if (nread < 0) { - LDBG(curlun, "error in file verify: %d\n", - (int) nread); - nread = 0; - } else if (nread < amount) { - LDBG(curlun, "partial file verify: %d/%u\n", - (int) nread, amount); - nread -= (nread & 511); /* Round down to a sector */ - } - if (nread == 0) { - curlun->sense_data = SS_UNRECOVERED_READ_ERROR; - curlun->sense_data_info = file_offset >> 9; - curlun->info_valid = 1; - break; - } - file_offset += nread; - amount_left -= nread; - } - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - u8 *buf = (u8 *) bh->buf; - - if (!curlun) { /* Unsupported LUNs are okay */ - common->bad_lun_okay = 1; - memset(buf, 0, 36); - buf[0] = 0x7f; /* Unsupported, no device-type */ - buf[4] = 31; /* Additional length */ - return 36; - } - - buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK; - buf[1] = curlun->removable ? 0x80 : 0; - buf[2] = 2; /* ANSI SCSI level 2 */ - buf[3] = 2; /* SCSI-2 INQUIRY data format */ - buf[4] = 31; /* Additional length */ - buf[5] = 0; /* No special options */ - buf[6] = 0; - buf[7] = 0; - memcpy(buf + 8, common->inquiry_string, sizeof common->inquiry_string); - return 36; -} - - -static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - u8 *buf = (u8 *) bh->buf; - u32 sd, sdinfo; - int valid; - - /* - * From the SCSI-2 spec., section 7.9 (Unit attention condition): - * - * If a REQUEST SENSE command is received from an initiator - * with a pending unit attention condition (before the target - * generates the contingent allegiance condition), then the - * target shall either: - * a) report any pending sense data and preserve the unit - * attention condition on the logical unit, or, - * b) report the unit attention condition, may discard any - * pending sense data, and clear the unit attention - * condition on the logical unit for that initiator. - * - * FSG normally uses option a); enable this code to use option b). - */ -#if 0 - if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { - curlun->sense_data = curlun->unit_attention_data; - curlun->unit_attention_data = SS_NO_SENSE; - } -#endif - - if (!curlun) { /* Unsupported LUNs are okay */ - common->bad_lun_okay = 1; - sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; - sdinfo = 0; - valid = 0; - } else { - sd = curlun->sense_data; - sdinfo = curlun->sense_data_info; - valid = curlun->info_valid << 7; - curlun->sense_data = SS_NO_SENSE; - curlun->sense_data_info = 0; - curlun->info_valid = 0; - } - - memset(buf, 0, 18); - buf[0] = valid | 0x70; /* Valid, current error */ - buf[2] = SK(sd); - put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ - buf[7] = 18 - 8; /* Additional sense length */ - buf[12] = ASC(sd); - buf[13] = ASCQ(sd); - return 18; -} - - -static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - u32 lba = get_unaligned_be32(&common->cmnd[2]); - int pmi = common->cmnd[8]; - u8 *buf = (u8 *) bh->buf; - - /* Check the PMI and LBA fields */ - if (pmi > 1 || (pmi == 0 && lba != 0)) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); - /* Max logical block */ - put_unaligned_be32(512, &buf[4]); /* Block length */ - return 8; -} - - -static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - int msf = common->cmnd[1] & 0x02; - u32 lba = get_unaligned_be32(&common->cmnd[2]); - u8 *buf = (u8 *) bh->buf; - - if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - if (lba >= curlun->num_sectors) { - curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; - return -EINVAL; - } - - memset(buf, 0, 8); - buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ - store_cdrom_address(&buf[4], msf, lba); - return 8; -} - - -static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - int msf = common->cmnd[1] & 0x02; - int start_track = common->cmnd[6]; - u8 *buf = (u8 *) bh->buf; - - if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ - start_track > 1) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - memset(buf, 0, 20); - buf[1] = (20-2); /* TOC data length */ - buf[2] = 1; /* First track number */ - buf[3] = 1; /* Last track number */ - buf[5] = 0x16; /* Data track, copying allowed */ - buf[6] = 0x01; /* Only track is number 1 */ - store_cdrom_address(&buf[8], msf, 0); - - buf[13] = 0x16; /* Lead-out track is data */ - buf[14] = 0xAA; /* Lead-out track number */ - store_cdrom_address(&buf[16], msf, curlun->num_sectors); - return 20; -} - - -static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - int mscmnd = common->cmnd[0]; - u8 *buf = (u8 *) bh->buf; - u8 *buf0 = buf; - int pc, page_code; - int changeable_values, all_pages; - int valid_page = 0; - int len, limit; - - if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - pc = common->cmnd[2] >> 6; - page_code = common->cmnd[2] & 0x3f; - if (pc == 3) { - curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; - return -EINVAL; - } - changeable_values = (pc == 1); - all_pages = (page_code == 0x3f); - - /* Write the mode parameter header. Fixed values are: default - * medium type, no cache control (DPOFUA), and no block descriptors. - * The only variable value is the WriteProtect bit. We will fill in - * the mode data length later. */ - memset(buf, 0, 8); - if (mscmnd == SC_MODE_SENSE_6) { - buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ - buf += 4; - limit = 255; - } else { /* SC_MODE_SENSE_10 */ - buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ - buf += 8; - limit = 65535; /* Should really be FSG_BUFLEN */ - } - - /* No block descriptors */ - - /* The mode pages, in numerical order. The only page we support - * is the Caching page. */ - if (page_code == 0x08 || all_pages) { - valid_page = 1; - buf[0] = 0x08; /* Page code */ - buf[1] = 10; /* Page length */ - memset(buf+2, 0, 10); /* None of the fields are changeable */ - - if (!changeable_values) { - buf[2] = 0x04; /* Write cache enable, */ - /* Read cache not disabled */ - /* No cache retention priorities */ - put_unaligned_be16(0xffff, &buf[4]); - /* Don't disable prefetch */ - /* Minimum prefetch = 0 */ - put_unaligned_be16(0xffff, &buf[8]); - /* Maximum prefetch */ - put_unaligned_be16(0xffff, &buf[10]); - /* Maximum prefetch ceiling */ - } - buf += 12; - } - - /* Check that a valid page was requested and the mode data length - * isn't too long. */ - len = buf - buf0; - if (!valid_page || len > limit) { - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - /* Store the mode data length */ - if (mscmnd == SC_MODE_SENSE_6) - buf0[0] = len - 1; - else - put_unaligned_be16(len - 2, buf0); - return len; -} - - -static int do_start_stop(struct fsg_common *common) -{ - if (!common->curlun) { - return -EINVAL; - } else if (!common->curlun->removable) { - common->curlun->sense_data = SS_INVALID_COMMAND; - return -EINVAL; - } - return 0; -} - - -static int do_prevent_allow(struct fsg_common *common) -{ - struct fsg_lun *curlun = common->curlun; - int prevent; - - if (!common->curlun) { - return -EINVAL; - } else if (!common->curlun->removable) { - common->curlun->sense_data = SS_INVALID_COMMAND; - return -EINVAL; - } - - prevent = common->cmnd[4] & 0x01; - if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - - if (curlun->prevent_medium_removal && !prevent) - fsg_lun_fsync_sub(curlun); - curlun->prevent_medium_removal = prevent; - return 0; -} - - -static int do_read_format_capacities(struct fsg_common *common, - struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - u8 *buf = (u8 *) bh->buf; - - buf[0] = buf[1] = buf[2] = 0; - buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ - buf += 4; - - put_unaligned_be32(curlun->num_sectors, &buf[0]); - /* Number of blocks */ - put_unaligned_be32(512, &buf[4]); /* Block length */ - buf[4] = 0x02; /* Current capacity */ - return 12; -} - - -static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) -{ - struct fsg_lun *curlun = common->curlun; - - /* We don't support MODE SELECT */ - if (curlun) - curlun->sense_data = SS_INVALID_COMMAND; - return -EINVAL; -} - - -/*-------------------------------------------------------------------------*/ - -static int halt_bulk_in_endpoint(struct fsg_dev *fsg) -{ - int rc; - - rc = fsg_set_halt(fsg, fsg->bulk_in); - if (rc == -EAGAIN) - VDBG(fsg, "delayed bulk-in endpoint halt\n"); - while (rc != 0) { - if (rc != -EAGAIN) { - WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); - rc = 0; - break; - } - - /* Wait for a short time and then try again */ - if (msleep_interruptible(100) != 0) - return -EINTR; - rc = usb_ep_set_halt(fsg->bulk_in); - } - return rc; -} - -static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) -{ - int rc; - - DBG(fsg, "bulk-in set wedge\n"); - rc = usb_ep_set_wedge(fsg->bulk_in); - if (rc == -EAGAIN) - VDBG(fsg, "delayed bulk-in endpoint wedge\n"); - while (rc != 0) { - if (rc != -EAGAIN) { - WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); - rc = 0; - break; - } - - /* Wait for a short time and then try again */ - if (msleep_interruptible(100) != 0) - return -EINTR; - rc = usb_ep_set_wedge(fsg->bulk_in); - } - return rc; -} - -static int pad_with_zeros(struct fsg_dev *fsg) -{ - struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; - u32 nkeep = bh->inreq->length; - u32 nsend; - int rc; - - bh->state = BUF_STATE_EMPTY; /* For the first iteration */ - fsg->common->usb_amount_left = nkeep + fsg->common->residue; - while (fsg->common->usb_amount_left > 0) { - - /* Wait for the next buffer to be free */ - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(fsg->common); - if (rc) - return rc; - } - - nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); - memset(bh->buf + nkeep, 0, nsend - nkeep); - bh->inreq->length = nsend; - bh->inreq->zero = 0; - start_transfer(fsg, fsg->bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state); - bh = fsg->common->next_buffhd_to_fill = bh->next; - fsg->common->usb_amount_left -= nsend; - nkeep = 0; - } - return 0; -} - -static int throw_away_data(struct fsg_common *common) -{ - struct fsg_buffhd *bh; - u32 amount; - int rc; - - for (bh = common->next_buffhd_to_drain; - bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; - bh = common->next_buffhd_to_drain) { - - /* Throw away the data in a filled buffer */ - if (bh->state == BUF_STATE_FULL) { - smp_rmb(); - bh->state = BUF_STATE_EMPTY; - common->next_buffhd_to_drain = bh->next; - - /* A short packet or an error ends everything */ - if (bh->outreq->actual != bh->outreq->length || - bh->outreq->status != 0) { - raise_exception(common, - FSG_STATE_ABORT_BULK_OUT); - return -EINTR; - } - continue; - } - - /* Try to submit another request if we need one */ - bh = common->next_buffhd_to_fill; - if (bh->state == BUF_STATE_EMPTY - && common->usb_amount_left > 0) { - amount = min(common->usb_amount_left, FSG_BUFLEN); - - /* amount is always divisible by 512, hence by - * the bulk-out maxpacket size */ - bh->outreq->length = amount; - bh->bulk_out_intended_length = amount; - bh->outreq->short_not_ok = 1; - START_TRANSFER_OR(common, bulk_out, bh->outreq, - &bh->outreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - return -EIO; - common->next_buffhd_to_fill = bh->next; - common->usb_amount_left -= amount; - continue; - } - - /* Otherwise wait for something to happen */ - rc = sleep_thread(common); - if (rc) - return rc; - } - return 0; -} - - -static int finish_reply(struct fsg_common *common) -{ - struct fsg_buffhd *bh = common->next_buffhd_to_fill; - int rc = 0; - - switch (common->data_dir) { - case DATA_DIR_NONE: - break; /* Nothing to send */ - - /* If we don't know whether the host wants to read or write, - * this must be CB or CBI with an unknown command. We mustn't - * try to send or receive any data. So stall both bulk pipes - * if we can and wait for a reset. */ - case DATA_DIR_UNKNOWN: - if (!common->can_stall) { - /* Nothing */ - } else if (fsg_is_set(common)) { - fsg_set_halt(common->fsg, common->fsg->bulk_out); - rc = halt_bulk_in_endpoint(common->fsg); - } else { - /* Don't know what to do if common->fsg is NULL */ - rc = -EIO; - } - break; - - /* All but the last buffer of data must have already been sent */ - case DATA_DIR_TO_HOST: - if (common->data_size == 0) { - /* Nothing to send */ - - /* If there's no residue, simply send the last buffer */ - } else if (common->residue == 0) { - bh->inreq->zero = 0; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - return -EIO; - common->next_buffhd_to_fill = bh->next; - - /* For Bulk-only, if we're allowed to stall then send the - * short packet and halt the bulk-in endpoint. If we can't - * stall, pad out the remaining data with 0's. */ - } else if (common->can_stall) { - bh->inreq->zero = 1; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - /* Don't know what to do if - * common->fsg is NULL */ - rc = -EIO; - common->next_buffhd_to_fill = bh->next; - if (common->fsg) - rc = halt_bulk_in_endpoint(common->fsg); - } else if (fsg_is_set(common)) { - rc = pad_with_zeros(common->fsg); - } else { - /* Don't know what to do if common->fsg is NULL */ - rc = -EIO; - } - break; - - /* We have processed all we want from the data the host has sent. - * There may still be outstanding bulk-out requests. */ - case DATA_DIR_FROM_HOST: - if (common->residue == 0) { - /* Nothing to receive */ - - /* Did the host stop sending unexpectedly early? */ - } else if (common->short_packet_received) { - raise_exception(common, FSG_STATE_ABORT_BULK_OUT); - rc = -EINTR; - - /* We haven't processed all the incoming data. Even though - * we may be allowed to stall, doing so would cause a race. - * The controller may already have ACK'ed all the remaining - * bulk-out packets, in which case the host wouldn't see a - * STALL. Not realizing the endpoint was halted, it wouldn't - * clear the halt -- leading to problems later on. */ -#if 0 - } else if (common->can_stall) { - if (fsg_is_set(common)) - fsg_set_halt(common->fsg, - common->fsg->bulk_out); - raise_exception(common, FSG_STATE_ABORT_BULK_OUT); - rc = -EINTR; -#endif - - /* We can't stall. Read in the excess data and throw it - * all away. */ - } else { - rc = throw_away_data(common); - } - break; - } - return rc; -} - - -static int send_status(struct fsg_common *common) -{ - struct fsg_lun *curlun = common->curlun; - struct fsg_buffhd *bh; - struct bulk_cs_wrap *csw; - int rc; - u8 status = USB_STATUS_PASS; - u32 sd, sdinfo = 0; - - /* Wait for the next buffer to become available */ - bh = common->next_buffhd_to_fill; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - if (curlun) { - sd = curlun->sense_data; - sdinfo = curlun->sense_data_info; - } else if (common->bad_lun_okay) - sd = SS_NO_SENSE; - else - sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; - - if (common->phase_error) { - DBG(common, "sending phase-error status\n"); - status = USB_STATUS_PHASE_ERROR; - sd = SS_INVALID_COMMAND; - } else if (sd != SS_NO_SENSE) { - DBG(common, "sending command-failure status\n"); - status = USB_STATUS_FAIL; - VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" - " info x%x\n", - SK(sd), ASC(sd), ASCQ(sd), sdinfo); - } - - /* Store and send the Bulk-only CSW */ - csw = (void *)bh->buf; - - csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); - csw->Tag = common->tag; - csw->Residue = cpu_to_le32(common->residue); - csw->Status = status; - - bh->inreq->length = USB_BULK_CS_WRAP_LEN; - bh->inreq->zero = 0; - START_TRANSFER_OR(common, bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state) - /* Don't know what to do if common->fsg is NULL */ - return -EIO; - - common->next_buffhd_to_fill = bh->next; - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* Check whether the command is properly formed and whether its data size - * and direction agree with the values we already have. */ -static int check_command(struct fsg_common *common, int cmnd_size, - enum data_direction data_dir, unsigned int mask, - int needs_medium, const char *name) -{ - int i; - int lun = common->cmnd[1] >> 5; - static const char dirletter[4] = {'u', 'o', 'i', 'n'}; - char hdlen[20]; - struct fsg_lun *curlun; - - hdlen[0] = 0; - if (common->data_dir != DATA_DIR_UNKNOWN) - sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], - common->data_size); - VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", - name, cmnd_size, dirletter[(int) data_dir], - common->data_size_from_cmnd, common->cmnd_size, hdlen); - - /* We can't reply at all until we know the correct data direction - * and size. */ - if (common->data_size_from_cmnd == 0) - data_dir = DATA_DIR_NONE; - if (common->data_size < common->data_size_from_cmnd) { - /* Host data size < Device data size is a phase error. - * Carry out the command, but only transfer as much as - * we are allowed. */ - common->data_size_from_cmnd = common->data_size; - common->phase_error = 1; - } - common->residue = common->data_size; - common->usb_amount_left = common->data_size; - - /* Conflicting data directions is a phase error */ - if (common->data_dir != data_dir - && common->data_size_from_cmnd > 0) { - common->phase_error = 1; - return -EINVAL; - } - - /* Verify the length of the command itself */ - if (cmnd_size != common->cmnd_size) { - - /* Special case workaround: There are plenty of buggy SCSI - * implementations. Many have issues with cbw->Length - * field passing a wrong command size. For those cases we - * always try to work around the problem by using the length - * sent by the host side provided it is at least as large - * as the correct command length. - * Examples of such cases would be MS-Windows, which issues - * REQUEST SENSE with cbw->Length == 12 where it should - * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and - * REQUEST SENSE with cbw->Length == 10 where it should - * be 6 as well. - */ - if (cmnd_size <= common->cmnd_size) { - DBG(common, "%s is buggy! Expected length %d " - "but we got %d\n", name, - cmnd_size, common->cmnd_size); - cmnd_size = common->cmnd_size; - } else { - common->phase_error = 1; - return -EINVAL; - } - } - - /* Check that the LUN values are consistent */ - if (common->lun != lun) - DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", - common->lun, lun); - - /* Check the LUN */ - if (common->lun >= 0 && common->lun < common->nluns) { - curlun = &common->luns[common->lun]; - common->curlun = curlun; - if (common->cmnd[0] != SC_REQUEST_SENSE) { - curlun->sense_data = SS_NO_SENSE; - curlun->sense_data_info = 0; - curlun->info_valid = 0; - } - } else { - common->curlun = NULL; - curlun = NULL; - common->bad_lun_okay = 0; - - /* INQUIRY and REQUEST SENSE commands are explicitly allowed - * to use unsupported LUNs; all others may not. */ - if (common->cmnd[0] != SC_INQUIRY && - common->cmnd[0] != SC_REQUEST_SENSE) { - DBG(common, "unsupported LUN %d\n", common->lun); - return -EINVAL; - } - } - - /* If a unit attention condition exists, only INQUIRY and - * REQUEST SENSE commands are allowed; anything else must fail. */ - if (curlun && curlun->unit_attention_data != SS_NO_SENSE && - common->cmnd[0] != SC_INQUIRY && - common->cmnd[0] != SC_REQUEST_SENSE) { - curlun->sense_data = curlun->unit_attention_data; - curlun->unit_attention_data = SS_NO_SENSE; - return -EINVAL; - } - - /* Check that only command bytes listed in the mask are non-zero */ - common->cmnd[1] &= 0x1f; /* Mask away the LUN */ - for (i = 1; i < cmnd_size; ++i) { - if (common->cmnd[i] && !(mask & (1 << i))) { - if (curlun) - curlun->sense_data = SS_INVALID_FIELD_IN_CDB; - return -EINVAL; - } - } - - /* If the medium isn't mounted and the command needs to access - * it, return an error. */ - if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { - curlun->sense_data = SS_MEDIUM_NOT_PRESENT; - return -EINVAL; - } - - return 0; -} - - -static int do_scsi_command(struct fsg_common *common) -{ - struct fsg_buffhd *bh; - int rc; - int reply = -EINVAL; - int i; - static char unknown[16]; - - dump_cdb(common); - - /* Wait for the next buffer to become available for data or status */ - bh = common->next_buffhd_to_fill; - common->next_buffhd_to_drain = bh; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - common->phase_error = 0; - common->short_packet_received = 0; - - down_read(&common->filesem); /* We're using the backing file */ - switch (common->cmnd[0]) { - - case SC_INQUIRY: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (1<<4), 0, - "INQUIRY"); - if (reply == 0) - reply = do_inquiry(common, bh); - break; - - case SC_MODE_SELECT_6: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_FROM_HOST, - (1<<1) | (1<<4), 0, - "MODE SELECT(6)"); - if (reply == 0) - reply = do_mode_select(common, bh); - break; - - case SC_MODE_SELECT_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_FROM_HOST, - (1<<1) | (3<<7), 0, - "MODE SELECT(10)"); - if (reply == 0) - reply = do_mode_select(common, bh); - break; - - case SC_MODE_SENSE_6: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (1<<1) | (1<<2) | (1<<4), 0, - "MODE SENSE(6)"); - if (reply == 0) - reply = do_mode_sense(common, bh); - break; - - case SC_MODE_SENSE_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (1<<1) | (1<<2) | (3<<7), 0, - "MODE SENSE(10)"); - if (reply == 0) - reply = do_mode_sense(common, bh); - break; - - case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: - common->data_size_from_cmnd = 0; - reply = check_command(common, 6, DATA_DIR_NONE, - (1<<4), 0, - "PREVENT-ALLOW MEDIUM REMOVAL"); - if (reply == 0) - reply = do_prevent_allow(common); - break; - - case SC_READ_6: - i = common->cmnd[4]; - common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (7<<1) | (1<<4), 1, - "READ(6)"); - if (reply == 0) - reply = do_read(common); - break; - - case SC_READ_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]) << 9; - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (1<<1) | (0xf<<2) | (3<<7), 1, - "READ(10)"); - if (reply == 0) - reply = do_read(common); - break; - - case SC_READ_12: - common->data_size_from_cmnd = - get_unaligned_be32(&common->cmnd[6]) << 9; - reply = check_command(common, 12, DATA_DIR_TO_HOST, - (1<<1) | (0xf<<2) | (0xf<<6), 1, - "READ(12)"); - if (reply == 0) - reply = do_read(common); - break; - - case SC_READ_CAPACITY: - common->data_size_from_cmnd = 8; - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (0xf<<2) | (1<<8), 1, - "READ CAPACITY"); - if (reply == 0) - reply = do_read_capacity(common, bh); - break; - - case SC_READ_HEADER: - if (!common->curlun || !common->curlun->cdrom) - goto unknown_cmnd; - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (3<<7) | (0x1f<<1), 1, - "READ HEADER"); - if (reply == 0) - reply = do_read_header(common, bh); - break; - - case SC_READ_TOC: - if (!common->curlun || !common->curlun->cdrom) - goto unknown_cmnd; - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (7<<6) | (1<<1), 1, - "READ TOC"); - if (reply == 0) - reply = do_read_toc(common, bh); - break; - - case SC_READ_FORMAT_CAPACITIES: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]); - reply = check_command(common, 10, DATA_DIR_TO_HOST, - (3<<7), 1, - "READ FORMAT CAPACITIES"); - if (reply == 0) - reply = do_read_format_capacities(common, bh); - break; - - case SC_REQUEST_SENSE: - common->data_size_from_cmnd = common->cmnd[4]; - reply = check_command(common, 6, DATA_DIR_TO_HOST, - (1<<4), 0, - "REQUEST SENSE"); - if (reply == 0) - reply = do_request_sense(common, bh); - break; - - case SC_START_STOP_UNIT: - common->data_size_from_cmnd = 0; - reply = check_command(common, 6, DATA_DIR_NONE, - (1<<1) | (1<<4), 0, - "START-STOP UNIT"); - if (reply == 0) - reply = do_start_stop(common); - break; - - case SC_SYNCHRONIZE_CACHE: - common->data_size_from_cmnd = 0; - reply = check_command(common, 10, DATA_DIR_NONE, - (0xf<<2) | (3<<7), 1, - "SYNCHRONIZE CACHE"); - if (reply == 0) - reply = do_synchronize_cache(common); - break; - - case SC_TEST_UNIT_READY: - common->data_size_from_cmnd = 0; - reply = check_command(common, 6, DATA_DIR_NONE, - 0, 1, - "TEST UNIT READY"); - break; - - /* Although optional, this command is used by MS-Windows. We - * support a minimal version: BytChk must be 0. */ - case SC_VERIFY: - common->data_size_from_cmnd = 0; - reply = check_command(common, 10, DATA_DIR_NONE, - (1<<1) | (0xf<<2) | (3<<7), 1, - "VERIFY"); - if (reply == 0) - reply = do_verify(common); - break; - - case SC_WRITE_6: - i = common->cmnd[4]; - common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; - reply = check_command(common, 6, DATA_DIR_FROM_HOST, - (7<<1) | (1<<4), 1, - "WRITE(6)"); - if (reply == 0) - reply = do_write(common); - break; - - case SC_WRITE_10: - common->data_size_from_cmnd = - get_unaligned_be16(&common->cmnd[7]) << 9; - reply = check_command(common, 10, DATA_DIR_FROM_HOST, - (1<<1) | (0xf<<2) | (3<<7), 1, - "WRITE(10)"); - if (reply == 0) - reply = do_write(common); - break; - - case SC_WRITE_12: - common->data_size_from_cmnd = - get_unaligned_be32(&common->cmnd[6]) << 9; - reply = check_command(common, 12, DATA_DIR_FROM_HOST, - (1<<1) | (0xf<<2) | (0xf<<6), 1, - "WRITE(12)"); - if (reply == 0) - reply = do_write(common); - break; - - /* Some mandatory commands that we recognize but don't implement. - * They don't mean much in this setting. It's left as an exercise - * for anyone interested to implement RESERVE and RELEASE in terms - * of Posix locks. */ - case SC_FORMAT_UNIT: - case SC_RELEASE: - case SC_RESERVE: - case SC_SEND_DIAGNOSTIC: - /* Fall through */ - - default: -unknown_cmnd: - common->data_size_from_cmnd = 0; - sprintf(unknown, "Unknown x%02x", common->cmnd[0]); - reply = check_command(common, common->cmnd_size, - DATA_DIR_UNKNOWN, 0xff, 0, unknown); - if (reply == 0) { - common->curlun->sense_data = SS_INVALID_COMMAND; - reply = -EINVAL; - } - break; - } - up_read(&common->filesem); - - if (reply == -EINTR || signal_pending(current)) - return -EINTR; - - /* Set up the single reply buffer for finish_reply() */ - if (reply == -EINVAL) - reply = 0; /* Error reply length */ - if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { - reply = min((u32) reply, common->data_size_from_cmnd); - bh->inreq->length = reply; - bh->state = BUF_STATE_FULL; - common->residue -= reply; - } /* Otherwise it's already set */ - - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ - struct usb_request *req = bh->outreq; - struct fsg_bulk_cb_wrap *cbw = req->buf; - struct fsg_common *common = fsg->common; - - /* Was this a real packet? Should it be ignored? */ - if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) - return -EINVAL; - - /* Is the CBW valid? */ - if (req->actual != USB_BULK_CB_WRAP_LEN || - cbw->Signature != cpu_to_le32( - USB_BULK_CB_SIG)) { - DBG(fsg, "invalid CBW: len %u sig 0x%x\n", - req->actual, - le32_to_cpu(cbw->Signature)); - - /* The Bulk-only spec says we MUST stall the IN endpoint - * (6.6.1), so it's unavoidable. It also says we must - * retain this state until the next reset, but there's - * no way to tell the controller driver it should ignore - * Clear-Feature(HALT) requests. - * - * We aren't required to halt the OUT endpoint; instead - * we can simply accept and discard any data received - * until the next reset. */ - wedge_bulk_in_endpoint(fsg); - set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - return -EINVAL; - } - - /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || - cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { - DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " - "cmdlen %u\n", - cbw->Lun, cbw->Flags, cbw->Length); - - /* We can do anything we want here, so let's stall the - * bulk pipes if we are allowed to. */ - if (common->can_stall) { - fsg_set_halt(fsg, fsg->bulk_out); - halt_bulk_in_endpoint(fsg); - } - return -EINVAL; - } - - /* Save the command for later */ - common->cmnd_size = cbw->Length; - memcpy(common->cmnd, cbw->CDB, common->cmnd_size); - if (cbw->Flags & USB_BULK_IN_FLAG) - common->data_dir = DATA_DIR_TO_HOST; - else - common->data_dir = DATA_DIR_FROM_HOST; - common->data_size = le32_to_cpu(cbw->DataTransferLength); - if (common->data_size == 0) - common->data_dir = DATA_DIR_NONE; - common->lun = cbw->Lun; - common->tag = cbw->Tag; - return 0; -} - - -static int get_next_command(struct fsg_common *common) -{ - struct fsg_buffhd *bh; - int rc = 0; - - /* Wait for the next buffer to become available */ - bh = common->next_buffhd_to_fill; - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); - if (rc) - return rc; - } - - /* Queue a request to read a Bulk-only CBW */ - set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); - bh->outreq->short_not_ok = 1; - START_TRANSFER_OR(common, bulk_out, bh->outreq, - &bh->outreq_busy, &bh->state) - /* Don't know what to do if common->fsg is NULL */ - return -EIO; - - /* We will drain the buffer in software, which means we - * can reuse it for the next filling. No need to advance - * next_buffhd_to_fill. */ - - /* Wait for the CBW to arrive */ - while (bh->state != BUF_STATE_FULL) { - rc = sleep_thread(common); - if (rc) - return rc; - } - smp_rmb(); - rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; - bh->state = BUF_STATE_EMPTY; - - return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep, - const struct usb_endpoint_descriptor *d) -{ - int rc; - - ep->driver_data = common; - rc = usb_ep_enable(ep, d); - if (rc) - ERROR(common, "can't enable %s, result %d\n", ep->name, rc); - return rc; -} - -static int alloc_request(struct fsg_common *common, struct usb_ep *ep, - struct usb_request **preq) -{ - *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (*preq) - return 0; - ERROR(common, "can't allocate request for %s\n", ep->name); - return -ENOMEM; -} - -/* - * Reset interface setting and re-init endpoint state (toggle etc). - * Call with altsetting < 0 to disable the interface. The only other - * available altsetting is 0, which enables the interface. - */ -static int do_set_interface(struct fsg_common *common, int altsetting) -{ - int rc = 0; - int i; - const struct usb_endpoint_descriptor *d; - - if (common->running) - DBG(common, "reset interface\n"); - -reset: - /* Deallocate the requests */ - if (common->prev_fsg) { - struct fsg_dev *fsg = common->prev_fsg; - - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - struct fsg_buffhd *bh = &common->buffhds[i]; - - if (bh->inreq) { - usb_ep_free_request(fsg->bulk_in, bh->inreq); - bh->inreq = NULL; - } - if (bh->outreq) { - usb_ep_free_request(fsg->bulk_out, bh->outreq); - bh->outreq = NULL; - } - } - - /* Disable the endpoints */ - if (fsg->bulk_in_enabled) { - usb_ep_disable(fsg->bulk_in); - fsg->bulk_in_enabled = 0; - } - if (fsg->bulk_out_enabled) { - usb_ep_disable(fsg->bulk_out); - fsg->bulk_out_enabled = 0; - } - - common->prev_fsg = 0; - } - - common->running = 0; - if (altsetting < 0 || rc != 0) - return rc; - - DBG(common, "set interface %d\n", altsetting); - - if (fsg_is_set(common)) { - struct fsg_dev *fsg = common->fsg; - common->prev_fsg = common->fsg; - - /* Enable the endpoints */ - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); - rc = enable_endpoint(common, fsg->bulk_in, d); - if (rc) - goto reset; - fsg->bulk_in_enabled = 1; - - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); - rc = enable_endpoint(common, fsg->bulk_out, d); - if (rc) - goto reset; - fsg->bulk_out_enabled = 1; - common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); - clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - - /* Allocate the requests */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - struct fsg_buffhd *bh = &common->buffhds[i]; - - rc = alloc_request(common, fsg->bulk_in, &bh->inreq); - if (rc) - goto reset; - rc = alloc_request(common, fsg->bulk_out, &bh->outreq); - if (rc) - goto reset; - bh->inreq->buf = bh->outreq->buf = bh->buf; - bh->inreq->context = bh->outreq->context = bh; - bh->inreq->complete = bulk_in_complete; - bh->outreq->complete = bulk_out_complete; - } - - common->running = 1; - for (i = 0; i < common->nluns; ++i) - common->luns[i].unit_attention_data = SS_RESET_OCCURRED; - return rc; - } else { - return -EIO; - } -} - - -/* - * Change our operational configuration. This code must agree with the code - * that returns config descriptors, and with interface altsetting code. - * - * It's also responsible for power management interactions. Some - * configurations might not work with our current power sources. - * For now we just assume the gadget is always self-powered. - */ -static int do_set_config(struct fsg_common *common, u8 new_config) -{ - int rc = 0; - - /* Disable the single interface */ - if (common->config != 0) { - DBG(common, "reset config\n"); - common->config = 0; - rc = do_set_interface(common, -1); - } - - /* Enable the interface */ - if (new_config != 0) { - common->config = new_config; - rc = do_set_interface(common, 0); - if (rc != 0) - common->config = 0; /* Reset on errors */ - } - return rc; -} - - -/****************************** ALT CONFIGS ******************************/ - - -static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -{ - struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->prev_fsg = fsg->common->fsg; - fsg->common->fsg = fsg; - fsg->common->new_config = 1; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); - return 0; -} - -static void fsg_disable(struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->prev_fsg = fsg->common->fsg; - fsg->common->fsg = fsg; - fsg->common->new_config = 0; - - DBG(common, "fsg_disable filp=%p\n", fsg->common->luns[0].filp); - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE_DISABLE); -} - -static void shutdown_server(void) { - DBG(fsg_common, "shutdown_server filp=%p\n", fsg_common->luns[0].filp); - if (fsg_common->luns[0].filp) { - uint32_t buf[512 / 4]; - loff_t file_offset_tmp = 512 * 50000; // make sure we're outside of FS area - int i; - - // this should shut down the nbd server, so that the caches are flushed - memset(buf, 0, sizeof(buf)); - buf[0] = 0x20da6d81; - buf[1] = 0x747e09d4; - - fsg_common->luns[0].filp->f_flags |= O_SYNC; - for (i = 0; i < 2; ++i) - vfs_write(fsg_common->luns[0].filp, - (char*)buf, 512, &file_offset_tmp); - } -} - - -/*-------------------------------------------------------------------------*/ - -static void handle_exception(struct fsg_common *common) -{ - siginfo_t info; - int sig; - int i; - struct fsg_buffhd *bh; - enum fsg_state old_state; - u8 new_config; - struct fsg_lun *curlun; - unsigned int exception_req_tag; - int rc; - - /* Clear the existing signals. Anything but SIGUSR1 is converted - * into a high-priority EXIT exception. */ - for (;;) { - sig = dequeue_signal_lock(current, ¤t->blocked, &info); - if (!sig) - break; - if (sig != SIGUSR1) { - if (common->state < FSG_STATE_EXIT) - DBG(common, "Main thread exiting on signal\n"); - raise_exception(common, FSG_STATE_EXIT); - } - } - - /* Cancel all the pending transfers */ - if (fsg_is_set(common)) { - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - bh = &common->buffhds[i]; - if (bh->inreq_busy) - usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); - if (bh->outreq_busy) - usb_ep_dequeue(common->fsg->bulk_out, - bh->outreq); - } - - /* Wait until everything is idle */ - for (;;) { - int num_active = 0; - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - bh = &common->buffhds[i]; - num_active += bh->inreq_busy + bh->outreq_busy; - } - if (num_active == 0) - break; - if (sleep_thread(common)) - return; - } - - /* Clear out the controller's fifos */ - if (common->fsg->bulk_in_enabled) - usb_ep_fifo_flush(common->fsg->bulk_in); - if (common->fsg->bulk_out_enabled) - usb_ep_fifo_flush(common->fsg->bulk_out); - } - - /* Reset the I/O buffer states and pointers, the SCSI - * state, and the exception. Then invoke the handler. */ - spin_lock_irq(&common->lock); - - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - bh = &common->buffhds[i]; - bh->state = BUF_STATE_EMPTY; - } - common->next_buffhd_to_fill = &common->buffhds[0]; - common->next_buffhd_to_drain = &common->buffhds[0]; - exception_req_tag = common->exception_req_tag; - new_config = common->new_config; - old_state = common->state; - - if (old_state == FSG_STATE_ABORT_BULK_OUT) - common->state = FSG_STATE_STATUS_PHASE; - else { - for (i = 0; i < common->nluns; ++i) { - curlun = &common->luns[i]; - curlun->prevent_medium_removal = 0; - curlun->sense_data = SS_NO_SENSE; - curlun->unit_attention_data = SS_NO_SENSE; - curlun->sense_data_info = 0; - curlun->info_valid = 0; - } - common->state = FSG_STATE_IDLE; - } - spin_unlock_irq(&common->lock); - - /* Carry out any extra actions required for the exception */ - switch (old_state) { - case FSG_STATE_ABORT_BULK_OUT: - send_status(common); - spin_lock_irq(&common->lock); - if (common->state == FSG_STATE_STATUS_PHASE) - common->state = FSG_STATE_IDLE; - spin_unlock_irq(&common->lock); - break; - - case FSG_STATE_RESET: - /* In case we were forced against our will to halt a - * bulk endpoint, clear the halt now. (The SuperH UDC - * requires this.) */ - if (!fsg_is_set(common)) - break; - if (test_and_clear_bit(IGNORE_BULK_OUT, - &common->fsg->atomic_bitflags)) - usb_ep_clear_halt(common->fsg->bulk_in); - - if (common->ep0_req_tag == exception_req_tag) - ep0_queue(common); /* Complete the status stage */ - - /* Technically this should go here, but it would only be - * a waste of time. Ditto for the INTERFACE_CHANGE and - * CONFIG_CHANGE cases. */ - /* for (i = 0; i < common->nluns; ++i) */ - /* common->luns[i].unit_attention_data = */ - /* SS_RESET_OCCURRED; */ - break; - - case FSG_STATE_CONFIG_CHANGE_DISABLE: - shutdown_server(); - // fall-through - case FSG_STATE_CONFIG_CHANGE: - rc = do_set_config(common, new_config); - if (common->ep0_req_tag != exception_req_tag) - break; - if (rc != 0) { /* STALL on errors */ - DBG(common, "ep0 set halt\n"); - usb_ep_set_halt(common->ep0); - } else { /* Complete the status stage */ - ep0_queue(common); - } - break; - - case FSG_STATE_EXIT: - case FSG_STATE_TERMINATED: - do_set_config(common, 0); /* Free resources */ - spin_lock_irq(&common->lock); - common->state = FSG_STATE_TERMINATED; /* Stop the thread */ - spin_unlock_irq(&common->lock); - break; - - case FSG_STATE_INTERFACE_CHANGE: - case FSG_STATE_DISCONNECT: - case FSG_STATE_COMMAND_PHASE: - case FSG_STATE_DATA_PHASE: - case FSG_STATE_STATUS_PHASE: - case FSG_STATE_IDLE: - break; - } -} - - -/*-------------------------------------------------------------------------*/ - -static int fsg_main_thread(void *common_) -{ - struct fsg_common *common = common_; - - /* Allow the thread to be killed by a signal, but set the signal mask - * to block everything but INT, TERM, KILL, and USR1. */ - allow_signal(SIGINT); - allow_signal(SIGTERM); - allow_signal(SIGKILL); - allow_signal(SIGUSR1); - - /* Allow the thread to be frozen */ - set_freezable(); - - /* Arrange for userspace references to be interpreted as kernel - * pointers. That way we can pass a kernel pointer to a routine - * that expects a __user pointer and it will work okay. */ - set_fs(get_ds()); - - /* The main loop */ - while (common->state != FSG_STATE_TERMINATED) { - if (exception_in_progress(common) || signal_pending(current)) { - handle_exception(common); - continue; - } - - if (!common->running) { - sleep_thread(common); - continue; - } - - if (get_next_command(common)) - continue; - - spin_lock_irq(&common->lock); - if (!exception_in_progress(common)) - common->state = FSG_STATE_DATA_PHASE; - spin_unlock_irq(&common->lock); - - if (do_scsi_command(common) || finish_reply(common)) - continue; - - spin_lock_irq(&common->lock); - if (!exception_in_progress(common)) - common->state = FSG_STATE_STATUS_PHASE; - spin_unlock_irq(&common->lock); - - if (send_status(common)) - continue; - - spin_lock_irq(&common->lock); - if (!exception_in_progress(common)) - common->state = FSG_STATE_IDLE; - spin_unlock_irq(&common->lock); - } - - spin_lock_irq(&common->lock); - common->thread_task = NULL; - spin_unlock_irq(&common->lock); - - if (common->thread_exits) - common->thread_exits(common); - - /* Let the unbind and cleanup routines know the thread has exited */ - complete_and_exit(&common->thread_notifier, 0); -} - - -/*************************** DEVICE ATTRIBUTES ***************************/ - -/* Write permission is checked per LUN in store_*() functions. */ -static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro); -static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file); - -static struct fsg_dev *_fsg; - -static int isActive(void) { - return _fsg->function.config->cdev->deactivations == 0 ? 1 : 0; -} - -static ssize_t fsg_show_active(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", isActive()); -} - -static ssize_t fsg_store_active(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int i; - - if (sscanf(buf, "%d", &i) != 1) - return -EINVAL; - - if (isActive() != i) { - if (i == 0) { - usb_function_deactivate(&_fsg->function); - } else if (i == 1) { - usb_function_activate(&_fsg->function); - } else { - return -EINVAL; - } - } - - return count; -} - -static DEVICE_ATTR(active, 0644, fsg_show_active, fsg_store_active); - - -/****************************** FSG COMMON ******************************/ - -static void fsg_common_release(struct kref *ref); - -static void fsg_lun_release(struct device *dev) -{ - /* Nothing needs to be done */ -} - -static inline void fsg_common_get(struct fsg_common *common) -{ - kref_get(&common->ref); -} - -static inline void fsg_common_put(struct fsg_common *common) -{ - kref_put(&common->ref, fsg_common_release); -} - - -static struct fsg_common *fsg_common_init(struct fsg_common *common, - struct usb_composite_dev *cdev, - struct fsg_config *cfg) -{ - struct usb_gadget *gadget = cdev->gadget; - struct fsg_buffhd *bh; - struct fsg_lun *curlun; - struct fsg_lun_config *lcfg; - int nluns, i, rc; - char *pathbuf; - - /* Find out how many LUNs there should be */ - nluns = cfg->nluns; - if (nluns < 1 || nluns > FSG_MAX_LUNS) { - dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); - return ERR_PTR(-EINVAL); - } - - /* Allocate? */ - if (!common) { - common = kzalloc(sizeof *common, GFP_KERNEL); - if (!common) - return ERR_PTR(-ENOMEM); - common->free_storage_on_release = 1; - } else { - memset(common, 0, sizeof common); - common->free_storage_on_release = 0; - } - - common->private_data = cfg->private_data; - - common->gadget = gadget; - common->ep0 = gadget->ep0; - common->ep0req = cdev->req; - - /* Maybe allocate device-global string IDs, and patch descriptors */ - if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { - rc = usb_string_id(cdev); - if (rc < 0) { - kfree(common); - return ERR_PTR(rc); - } - fsg_strings[FSG_STRING_INTERFACE].id = rc; - fsg_intf_desc.iInterface = rc; - } - - /* Create the LUNs, open their backing files, and register the - * LUN devices in sysfs. */ - curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL); - if (!curlun) { - kfree(common); - return ERR_PTR(-ENOMEM); - } - common->luns = curlun; - - init_rwsem(&common->filesem); - - for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { - curlun->cdrom = !!lcfg->cdrom; - curlun->ro = lcfg->cdrom || lcfg->ro; - curlun->removable = lcfg->removable; - curlun->dev.release = fsg_lun_release; - curlun->dev.parent = &gadget->dev; - /* curlun->dev.driver = &fsg_driver.driver; XXX */ - dev_set_drvdata(&curlun->dev, &common->filesem); - dev_set_name(&curlun->dev, - cfg->lun_name_format - ? cfg->lun_name_format - : "lun%d", - i); - - rc = device_register(&curlun->dev); - if (rc) { - INFO(common, "failed to register LUN%d: %d\n", i, rc); - common->nluns = i; - goto error_release; - } - - rc = device_create_file(&curlun->dev, &dev_attr_ro); - if (rc) - goto error_luns; - rc = device_create_file(&curlun->dev, &dev_attr_file); - if (rc) - goto error_luns; - - rc = device_create_file(&curlun->dev, &dev_attr_active); - if (rc) - goto error_luns; - - if (lcfg->filename) { - rc = fsg_lun_open(curlun, lcfg->filename); - if (rc) - goto error_luns; - } else if (!curlun->removable) { - ERROR(common, "no file given for LUN%d\n", i); - rc = -EINVAL; - goto error_luns; - } - } - common->nluns = nluns; - - - /* Data buffers cyclic list */ - /* Buffers in buffhds are static -- no need for additional - * allocation. */ - bh = common->buffhds; - i = FSG_NUM_BUFFERS - 1; - do { - bh->next = bh + 1; - } while (++bh, --i); - bh->next = common->buffhds; - - - /* Prepare inquiryString */ - if (cfg->release != 0xffff) { - i = cfg->release; - } else { - /* The sa1100 controller is not supported */ - i = gadget_is_sa1100(gadget) - ? -1 - : usb_gadget_controller_number(gadget); - if (i >= 0) { - i = 0x0300 + i; - } else { - WARNING(common, "controller '%s' not recognized\n", - gadget->name); - i = 0x0399; - } - } -#define OR(x, y) ((x) ? (x) : (y)) - snprintf(common->inquiry_string, sizeof common->inquiry_string, - "%-8s%-16s%04x", - OR(cfg->vendor_name, "Linux "), - /* Assume product name dependent on the first LUN */ - OR(cfg->product_name, common->luns->cdrom - ? "File-Stor Gadget" - : "File-CD Gadget "), - i); - - - /* Some peripheral controllers are known not to be able to - * halt bulk endpoints correctly. If one of them is present, - * disable stalls. - */ - common->can_stall = cfg->can_stall && - !(gadget_is_sh(common->gadget) || - gadget_is_at91(common->gadget)); - - - spin_lock_init(&common->lock); - kref_init(&common->ref); - - - /* Tell the thread to start working */ - common->thread_exits = cfg->thread_exits; - common->thread_task = - kthread_create(fsg_main_thread, common, - OR(cfg->thread_name, "file-storage")); - if (IS_ERR(common->thread_task)) { - rc = PTR_ERR(common->thread_task); - goto error_release; - } - init_completion(&common->thread_notifier); -#undef OR - - - /* Information */ - INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); - INFO(common, "Number of LUNs=%d\n", common->nluns); - - pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); - for (i = 0, nluns = common->nluns, curlun = common->luns; - i < nluns; - ++curlun, ++i) { - char *p = "(no medium)"; - if (fsg_lun_is_open(curlun)) { - p = "(error)"; - if (pathbuf) { - p = d_path(&curlun->filp->f_path, - pathbuf, PATH_MAX); - if (IS_ERR(p)) - p = "(error)"; - } - } - LINFO(curlun, "LUN: %s%s%sfile: %s\n", - curlun->removable ? "removable " : "", - curlun->ro ? "read only " : "", - curlun->cdrom ? "CD-ROM " : "", - p); - } - kfree(pathbuf); - - DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); - - wake_up_process(common->thread_task); - - return common; - - -error_luns: - common->nluns = i + 1; -error_release: - common->state = FSG_STATE_TERMINATED; /* The thread is dead */ - /* Call fsg_common_release() directly, ref might be not - * initialised */ - fsg_common_release(&common->ref); - complete(&common->thread_notifier); - return ERR_PTR(rc); -} - - -static void fsg_common_release(struct kref *ref) -{ - struct fsg_common *common = - container_of(ref, struct fsg_common, ref); - unsigned i = common->nluns; - struct fsg_lun *lun = common->luns; - - /* If the thread isn't already dead, tell it to exit now */ - if (common->state != FSG_STATE_TERMINATED) { - raise_exception(common, FSG_STATE_EXIT); - wait_for_completion(&common->thread_notifier); - - /* The cleanup routine waits for this completion also */ - complete(&common->thread_notifier); - } - - /* Beware tempting for -> do-while optimization: when in error - * recovery nluns may be zero. */ - - for (; i; --i, ++lun) { - device_remove_file(&lun->dev, &dev_attr_ro); - device_remove_file(&lun->dev, &dev_attr_file); - fsg_lun_close(lun); - device_unregister(&lun->dev); - } - - kfree(common->luns); - if (common->free_storage_on_release) - kfree(common); -} - - -/*-------------------------------------------------------------------------*/ - - -static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - - DBG(fsg, "unbind\n"); - fsg_common_put(fsg->common); - kfree(fsg); -} - - -static int fsg_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct fsg_dev *fsg = fsg_from_func(f); - struct usb_gadget *gadget = c->cdev->gadget; - int rc; - int i; - struct usb_ep *ep; - - fsg->gadget = gadget; - - /* New interface */ - i = usb_interface_id(c, f); - if (i < 0) - return i; - fsg_intf_desc.bInterfaceNumber = i; - fsg->interface_number = i; - - /* Find all the endpoints we will use */ - ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); - if (!ep) - goto autoconf_fail; - ep->driver_data = fsg->common; /* claim the endpoint */ - fsg->bulk_in = ep; - - ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); - if (!ep) - goto autoconf_fail; - ep->driver_data = fsg->common; /* claim the endpoint */ - fsg->bulk_out = ep; - - if (gadget_is_dualspeed(gadget)) { - /* Assume endpoint addresses are the same for both speeds */ - fsg_hs_bulk_in_desc.bEndpointAddress = - fsg_fs_bulk_in_desc.bEndpointAddress; - fsg_hs_bulk_out_desc.bEndpointAddress = - fsg_fs_bulk_out_desc.bEndpointAddress; - f->hs_descriptors = fsg_hs_function; - } - - return 0; - -autoconf_fail: - ERROR(fsg, "unable to autoconfigure all endpoints\n"); - rc = -ENOTSUPP; - fsg_unbind(c, f); - return rc; -} - - -/****************************** ADD FUNCTION ******************************/ - -static struct usb_gadget_strings *fsg_strings_array[] = { - &fsg_stringtab, - NULL, -}; - -static int fsg_add(struct usb_composite_dev *cdev, - struct usb_configuration *c, - struct fsg_common *common) -{ - struct fsg_dev *fsg; - int rc; - - fsg = kzalloc(sizeof *fsg, GFP_KERNEL); - _fsg = fsg; - if (unlikely(!fsg)) - return -ENOMEM; - - fsg->function.name = FSG_DRIVER_DESC; - fsg->function.strings = fsg_strings_array; - fsg->function.descriptors = fsg_fs_function; - fsg->function.bind = fsg_bind; - fsg->function.unbind = fsg_unbind; - fsg->function.setup = fsg_setup; - fsg->function.set_alt = fsg_set_alt; - fsg->function.disable = fsg_disable; - - fsg->common = common; - /* Our caller holds a reference to common structure so we - * don't have to be worry about it being freed until we return - * from this function. So instead of incrementing counter now - * and decrement in error recovery we increment it only when - * call to usb_add_function() was successful. */ - - rc = usb_add_function(c, &fsg->function); - - if (likely(rc == 0)) - fsg_common_get(fsg->common); - else - kfree(fsg); - - return rc; -} - - - -/************************* Module parameters *************************/ - - -struct fsg_module_parameters { - char *file[FSG_MAX_LUNS]; - int ro[FSG_MAX_LUNS]; - int removable[FSG_MAX_LUNS]; - int cdrom[FSG_MAX_LUNS]; - - unsigned int file_count, ro_count, removable_count, cdrom_count; - unsigned int luns; /* nluns */ - int stall; /* can_stall */ -}; - - -#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ - module_param_array_named(prefix ## name, params.name, type, \ - &prefix ## params.name ## _count, \ - S_IRUGO); \ - MODULE_PARM_DESC(prefix ## name, desc) - -#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ - module_param_named(prefix ## name, params.name, type, \ - S_IRUGO); \ - MODULE_PARM_DESC(prefix ## name, desc) - -#define FSG_MODULE_PARAMETERS(prefix, params) \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ - "names of backing files or devices"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ - "true to force read-only"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ - "true to simulate removable media"); \ - _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ - "true to simulate CD-ROM instead of disk"); \ - _FSG_MODULE_PARAM(prefix, params, luns, uint, \ - "number of LUNs"); \ - _FSG_MODULE_PARAM(prefix, params, stall, bool, \ - "false to prevent bulk stalls") - - -static void -fsg_config_from_params(struct fsg_config *cfg, - const struct fsg_module_parameters *params) -{ - struct fsg_lun_config *lun; - unsigned i; - - /* Configure LUNs */ - cfg->nluns = - min(params->luns ?: (params->file_count ?: 1u), - (unsigned)FSG_MAX_LUNS); - for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) { - lun->ro = !!params->ro[i]; - lun->cdrom = !!params->cdrom[i]; - lun->removable = /* Removable by default */ - params->removable_count <= i || params->removable[i]; - lun->filename = - params->file_count > i && params->file[i][0] - ? params->file[i] - : 0; - } - - /* Let MSF use defaults */ - cfg->lun_name_format = 0; - cfg->thread_name = 0; - cfg->vendor_name = 0; - cfg->product_name = 0; - cfg->release = 0xffff; - - cfg->thread_exits = 0; - cfg->private_data = 0; - - /* Finalise */ - cfg->can_stall = params->stall; -} - -static inline struct fsg_common * -fsg_common_from_params(struct fsg_common *common, - struct usb_composite_dev *cdev, - const struct fsg_module_parameters *params) - __attribute__((unused)); -static inline struct fsg_common * -fsg_common_from_params(struct fsg_common *common, - struct usb_composite_dev *cdev, - const struct fsg_module_parameters *params) -{ - struct fsg_config cfg; - fsg_config_from_params(&cfg, params); - return fsg_common_init(common, cdev, &cfg); -} - diff --git a/brick/kernel/gadget_chips.h b/brick/kernel/gadget_chips.h deleted file mode 100644 index f2d270b2..00000000 --- a/brick/kernel/gadget_chips.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * USB device controllers have lots of quirks. Use these macros in - * gadget drivers or other code that needs to deal with them, and which - * autoconfigures instead of using early binding to the hardware. - * - * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by - * some config file that gets updated as new hardware is supported. - * (And avoiding all runtime comparisons in typical one-choice configs!) - * - * NOTE: some of these controller drivers may not be available yet. - * Some are available on 2.4 kernels; several are available, but not - * yet pushed in the 2.6 mainline tree. - */ - -#ifndef __GADGET_CHIPS_H -#define __GADGET_CHIPS_H - -#ifdef CONFIG_USB_GADGET_NET2280 -#define gadget_is_net2280(g) !strcmp("net2280", (g)->name) -#else -#define gadget_is_net2280(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_AMD5536UDC -#define gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name) -#else -#define gadget_is_amd5536udc(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_DUMMY_HCD -#define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name) -#else -#define gadget_is_dummy(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_PXA25X -#define gadget_is_pxa(g) !strcmp("pxa25x_udc", (g)->name) -#else -#define gadget_is_pxa(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_GOKU -#define gadget_is_goku(g) !strcmp("goku_udc", (g)->name) -#else -#define gadget_is_goku(g) 0 -#endif - -/* SH3 UDC -- not yet ported 2.4 --> 2.6 */ -#ifdef CONFIG_USB_GADGET_SUPERH -#define gadget_is_sh(g) !strcmp("sh_udc", (g)->name) -#else -#define gadget_is_sh(g) 0 -#endif - -/* not yet stable on 2.6 (would help "original Zaurus") */ -#ifdef CONFIG_USB_GADGET_SA1100 -#define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name) -#else -#define gadget_is_sa1100(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_LH7A40X -#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name) -#else -#define gadget_is_lh7a40x(g) 0 -#endif - -/* handhelds.org tree (?) */ -#ifdef CONFIG_USB_GADGET_MQ11XX -#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name) -#else -#define gadget_is_mq11xx(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_OMAP -#define gadget_is_omap(g) !strcmp("omap_udc", (g)->name) -#else -#define gadget_is_omap(g) 0 -#endif - -/* not yet ported 2.4 --> 2.6 */ -#ifdef CONFIG_USB_GADGET_N9604 -#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name) -#else -#define gadget_is_n9604(g) 0 -#endif - -/* various unstable versions available */ -#ifdef CONFIG_USB_GADGET_PXA27X -#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name) -#else -#define gadget_is_pxa27x(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_ATMEL_USBA -#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name) -#else -#define gadget_is_atmel_usba(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_S3C2410 -#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name) -#else -#define gadget_is_s3c2410(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_AT91 -#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name) -#else -#define gadget_is_at91(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_IMX -#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name) -#else -#define gadget_is_imx(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_FSL_USB2 -#define gadget_is_fsl_usb2(g) !strcmp("fsl-usb2-udc", (g)->name) -#else -#define gadget_is_fsl_usb2(g) 0 -#endif - -/* Mentor high speed function controller */ -/* from Montavista kernel (?) */ -#ifdef CONFIG_USB_GADGET_MUSBHSFC -#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name) -#else -#define gadget_is_musbhsfc(g) 0 -#endif - -/* Mentor high speed "dual role" controller, in peripheral role */ -#ifdef CONFIG_USB_GADGET_MUSB_HDRC -#define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name) -#else -#define gadget_is_musbhdrc(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_LANGWELL -#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name)) -#else -#define gadget_is_langwell(g) 0 -#endif - -/* from Montavista kernel (?) */ -#ifdef CONFIG_USB_GADGET_MPC8272 -#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name) -#else -#define gadget_is_mpc8272(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_M66592 -#define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name) -#else -#define gadget_is_m66592(g) 0 -#endif - -/* Freescale CPM/QE UDC SUPPORT */ -#ifdef CONFIG_USB_GADGET_FSL_QE -#define gadget_is_fsl_qe(g) !strcmp("fsl_qe_udc", (g)->name) -#else -#define gadget_is_fsl_qe(g) 0 -#endif - -#ifdef CONFIG_USB_GADGET_CI13XXX -#define gadget_is_ci13xxx(g) (!strcmp("ci13xxx_udc", (g)->name)) -#else -#define gadget_is_ci13xxx(g) 0 -#endif - -// CONFIG_USB_GADGET_SX2 -// CONFIG_USB_GADGET_AU1X00 -// ... - -#ifdef CONFIG_USB_GADGET_R8A66597 -#define gadget_is_r8a66597(g) !strcmp("r8a66597_udc", (g)->name) -#else -#define gadget_is_r8a66597(g) 0 -#endif - - -/** - * usb_gadget_controller_number - support bcdDevice id convention - * @gadget: the controller being driven - * - * Return a 2-digit BCD value associated with the peripheral controller, - * suitable for use as part of a bcdDevice value, or a negative error code. - * - * NOTE: this convention is purely optional, and has no meaning in terms of - * any USB specification. If you want to use a different convention in your - * gadget driver firmware -- maybe a more formal revision ID -- feel free. - * - * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) - * to change their behavior accordingly. For example it might help avoiding - * some chip bug. - */ -static inline int usb_gadget_controller_number(struct usb_gadget *gadget) -{ - if (gadget_is_net2280(gadget)) - return 0x01; - else if (gadget_is_dummy(gadget)) - return 0x02; - else if (gadget_is_pxa(gadget)) - return 0x03; - else if (gadget_is_sh(gadget)) - return 0x04; - else if (gadget_is_sa1100(gadget)) - return 0x05; - else if (gadget_is_goku(gadget)) - return 0x06; - else if (gadget_is_mq11xx(gadget)) - return 0x07; - else if (gadget_is_omap(gadget)) - return 0x08; - else if (gadget_is_lh7a40x(gadget)) - return 0x09; - else if (gadget_is_n9604(gadget)) - return 0x10; - else if (gadget_is_pxa27x(gadget)) - return 0x11; - else if (gadget_is_s3c2410(gadget)) - return 0x12; - else if (gadget_is_at91(gadget)) - return 0x13; - else if (gadget_is_imx(gadget)) - return 0x14; - else if (gadget_is_musbhsfc(gadget)) - return 0x15; - else if (gadget_is_musbhdrc(gadget)) - return 0x16; - else if (gadget_is_mpc8272(gadget)) - return 0x17; - else if (gadget_is_atmel_usba(gadget)) - return 0x18; - else if (gadget_is_fsl_usb2(gadget)) - return 0x19; - else if (gadget_is_amd5536udc(gadget)) - return 0x20; - else if (gadget_is_m66592(gadget)) - return 0x21; - else if (gadget_is_fsl_qe(gadget)) - return 0x22; - else if (gadget_is_ci13xxx(gadget)) - return 0x23; - else if (gadget_is_langwell(gadget)) - return 0x24; - else if (gadget_is_r8a66597(gadget)) - return 0x25; - return -ENOENT; -} - - -/** - * gadget_supports_altsettings - return true if altsettings work - * @gadget: the gadget in question - */ -static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) -{ - /* PXA 21x/25x/26x has no altsettings at all */ - if (gadget_is_pxa(gadget)) - return false; - - /* PXA 27x and 3xx have *broken* altsetting support */ - if (gadget_is_pxa27x(gadget)) - return false; - - /* SH3 hardware just doesn't do altsettings */ - if (gadget_is_sh(gadget)) - return false; - - /* Everything else is *presumably* fine ... */ - return true; -} - -#endif /* __GADGET_CHIPS_H */ diff --git a/brick/kernel/source/am1808.h b/brick/kernel/source/am1808.h deleted file mode 100755 index 8047520b..00000000 --- a/brick/kernel/source/am1808.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef AM1808_H_ -#define AM1808_H_ - -#ifndef PCASM -#include -#else -#define __iomem -#endif - -enum -{ - GP0_0,GP0_1,GP0_2,GP0_3,GP0_4,GP0_5,GP0_6,GP0_7,GP0_8,GP0_9,GP0_10,GP0_11,GP0_12,GP0_13,GP0_14,GP0_15, - GP1_0,GP1_1,GP1_2,GP1_3,GP1_4,GP1_5,GP1_6,GP1_7,GP1_8,GP1_9,GP1_10,GP1_11,GP1_12,GP1_13,GP1_14,GP1_15, - GP2_0,GP2_1,GP2_2,GP2_3,GP2_4,GP2_5,GP2_6,GP2_7,GP2_8,GP2_9,GP2_10,GP2_11,GP2_12,GP2_13,GP2_14,GP2_15, - GP3_0,GP3_1,GP3_2,GP3_3,GP3_4,GP3_5,GP3_6,GP3_7,GP3_8,GP3_9,GP3_10,GP3_11,GP3_12,GP3_13,GP3_14,GP3_15, - GP4_0,GP4_1,GP4_2,GP4_3,GP4_4,GP4_5,GP4_6,GP4_7,GP4_8,GP4_9,GP4_10,GP4_11,GP4_12,GP4_13,GP4_14,GP4_15, - GP5_0,GP5_1,GP5_2,GP5_3,GP5_4,GP5_5,GP5_6,GP5_7,GP5_8,GP5_9,GP5_10,GP5_11,GP5_12,GP5_13,GP5_14,GP5_15, - GP6_0,GP6_1,GP6_2,GP6_3,GP6_4,GP6_5,GP6_6,GP6_7,GP6_8,GP6_9,GP6_10,GP6_11,GP6_12,GP6_13,GP6_14,GP6_15, - GP7_0,GP7_1,GP7_2,GP7_3,GP7_4,GP7_5,GP7_6,GP7_7,GP7_8,GP7_9,GP7_10,GP7_11,GP7_12,GP7_13,GP7_14,GP7_15, - GP8_0,GP8_1,GP8_2,GP8_3,GP8_4,GP8_5,GP8_6,GP8_7,GP8_8,GP8_9,GP8_10,GP8_11,GP8_12,GP8_13,GP8_14,GP8_15, - NO_OF_GPIOS, - UART0_TXD,UART0_RXD,UART1_TXD,UART1_RXD, - SPI0_MOSI,SPI0_MISO,SPI0_SCL,SPI0_CS, - SPI1_MOSI,SPI1_MISO,SPI1_SCL,SPI1_CS, - EPWM1A,EPWM1B,APWM0,APWM1,EPWM0B,AXR3,AXR4 -}; - - -typedef struct -{ - int Pin; - u16 MuxReg; - u32 Mask; - u32 Mode; -} -MRM; - -MRM MuxRegMap[] = -{ // Pin MuxReg Mask Mode - - { GP0_1 , 1, 0xF0FFFFFF, 0x08000000 }, - { GP0_2 , 1, 0xFF0FFFFF, 0x00800000 }, - { GP0_3 , 1, 0xFFF0FFFF, 0x00080000 }, - { GP0_4 , 1, 0xFFFF0FFF, 0x00008000 }, - { GP0_5 , 1, 0xFFFFF0FF, 0x00000800 }, - { GP0_6 , 1, 0xFFFFFF0F, 0x00000080 }, - { GP0_7 , 1, 0xFFFFFFF0, 0x00000008 }, - - { GP0_11, 0, 0xFFF0FFFF, 0x00080000 }, - { GP0_12, 0, 0xFFFF0FFF, 0x00008000 }, - { GP0_13, 0, 0xFFFFF0FF, 0x00000800 }, - { GP0_14, 0, 0xFFFFFF0F, 0x00000080 }, - { GP0_15, 0, 0xFFFFFFF0, 0x00000008 }, - - { GP1_0 , 4, 0x0FFFFFFF, 0x80000000 }, - { GP1_8 , 3, 0xFFFFFFF0, 0x00000004 }, - - { GP1_9, 2, 0xF0FFFFFF, 0x04000000 }, - { GP1_10, 2, 0xFF0FFFFF, 0x00400000 }, - { GP1_11, 2, 0xFFF0FFFF, 0x00040000 }, - { GP1_12, 2, 0xFFFF0FFF, 0x00004000 }, - { GP1_13, 2, 0xFFFFF0FF, 0x00000400 }, - { GP1_14, 2, 0xFFFFFF0F, 0x00000040 }, - { GP1_15, 2, 0xFFFFFFF0, 0x00000008 }, - - { GP2_0, 6, 0x0FFFFFFF, 0x80000000 }, - { GP2_1, 6, 0xF0FFFFFF, 0x08000000 }, - { GP2_2, 6, 0xFF0FFFFF, 0x00800000 }, - { GP2_3, 6, 0xFFF0FFFF, 0x00080000 }, - { GP2_4, 6, 0xFFFF0FFF, 0x00008000 }, - { GP2_5, 6, 0xFFFFF0FF, 0x00000800 }, - { GP2_6, 6, 0xFFFFFF0F, 0x00000080 }, - { GP2_7, 6, 0xFFFFFFF0, 0x00000008 }, - - { GP2_8, 5, 0x0FFFFFFF, 0x80000000 }, - { GP2_9, 5, 0xF0FFFFFF, 0x08000000 }, - { GP2_10, 5, 0xFF0FFFFF, 0x00800000 }, - { GP2_11, 5, 0xFFF0FFFF, 0x00080000 }, - { GP2_12, 5, 0xFFFF0FFF, 0x00008000 }, - { GP2_13, 5, 0xFFFFF0FF, 0x00000800 }, - - { GP3_0, 8, 0x0FFFFFFF, 0x80000000 }, - { GP3_1 , 8, 0xF0FFFFFF, 0x08000000 }, - { GP3_2, 8, 0xFF0FFFFF, 0x00800000 }, - { GP3_3, 8, 0xFFF0FFFF, 0x00080000 }, - { GP3_4, 8, 0xFFFF0FFF, 0x00008000 }, - { GP3_5, 8, 0xFFFFF0FF, 0x00000800 }, - { GP3_6, 8, 0xFFFFFF0F, 0x00000080 }, - { GP3_7, 8, 0xFFFFFFF0, 0x00000008 }, - - { GP3_8, 7, 0x0FFFFFFF, 0x80000000 }, - { GP3_9, 7, 0xF0FFFFFF, 0x08000000 }, - { GP3_10, 7, 0xFF0FFFFF, 0x00800000 }, - { GP3_11, 7, 0xFFF0FFFF, 0x00080000 }, - { GP3_12, 7, 0xFFFF0FFF, 0x00008000 }, - { GP3_13, 7, 0xFFFFF0FF, 0x00000800 }, - { GP3_14, 7, 0xFFFFFF0F, 0x00000080 }, - { GP3_15, 7, 0xFFFFFFF0, 0x00000008 }, - - { GP4_1, 10, 0xF0FFFFFF, 0x08000000 }, - - { GP4_8, 9, 0x0FFFFFFF, 0x80000000 }, - { GP4_9, 9, 0xF0FFFFFF, 0x08000000 }, - { GP4_10, 9, 0xFF0FFFFF, 0x00800000 }, - - { GP4_12, 9, 0xFFFF0FFF, 0x00008000 }, - - { GP4_14, 9, 0xFFFFFF0F, 0x00000080 }, - - { GP5_0, 12, 0x0FFFFFFF, 0x80000000 }, - { GP5_1, 12, 0xF0FFFFFF, 0x08000000 }, - { GP5_2, 12, 0xFF0FFFFF, 0x00800000 }, - { GP5_3, 12, 0xFFF0FFFF, 0x00080000 }, - { GP5_4, 12, 0xFFFF0FFF, 0x00008000 }, - { GP5_5, 12, 0xFFFFF0FF, 0x00000800 }, - { GP5_6, 12, 0xFFFFFF0F, 0x00000080 }, - { GP5_7, 12, 0xFFFFFFF0, 0x00000008 }, - - { GP5_8, 11, 0x0FFFFFFF, 0x80000000 }, - { GP5_9, 11, 0xF0FFFFFF, 0x08000000 }, - { GP5_10, 11, 0xFF0FFFFF, 0x00800000 }, - { GP5_11, 11, 0xFFF0FFFF, 0x00080000 }, - { GP5_12, 11, 0xFFFF0FFF, 0x00008000 }, - { GP5_13, 11, 0xFFFFF0FF, 0x00000800 }, - { GP5_14, 11, 0xFFFFFF0F, 0x00000080 }, - { GP5_15, 11, 0xFFFFFFF0, 0x00000008 }, - - { GP6_0 , 19, 0xF0FFFFFF, 0x08000000 }, - { GP6_1, 19, 0xFF0FFFFF, 0x00800000 }, - { GP6_2, 19, 0xFFF0FFFF, 0x00080000 }, - { GP6_3, 19, 0xFFFF0FFF, 0x00008000 }, - { GP6_4, 19, 0xFFFFF0FF, 0x00000800 }, - { GP6_5, 16, 0xFFFFFF0F, 0x00000080 }, - - { GP6_6, 14, 0xFFFFFF0F, 0x00000080 }, - { GP6_7, 14, 0xFFFFFFF0, 0x00000008 }, - - { GP6_8, 13, 0x0FFFFFFF, 0x80000000 }, - { GP6_9, 13, 0xF0FFFFFF, 0x08000000 }, - { GP6_10, 13, 0xFF0FFFFF, 0x00800000 }, - { GP6_11, 13, 0xFFF0FFFF, 0x00080000 }, - { GP6_12, 13, 0xFFFF0FFF, 0x00008000 }, - { GP6_13, 13, 0xFFFFF0FF, 0x00000800 }, - { GP6_14, 13, 0xFFFFFF0F, 0x00000080 }, - { GP6_15, 13, 0xFFFFFFF0, 0x00000008 }, - - { GP7_4, 17, 0xFF0FFFFF, 0x00800000 }, - { GP7_8, 17, 0xFFFFFF0F, 0x00000080 }, - { GP7_9, 17, 0xFFFFFFF0, 0x00000008 }, - { GP7_10, 16, 0x0FFFFFFF, 0x80000000 }, - { GP7_11, 16, 0xF0FFFFFF, 0x08000000 }, - { GP7_12, 16, 0xFF0FFFFF, 0x00800000 }, - { GP7_13, 16, 0xFFF0FFFF, 0x00080000 }, - { GP7_14, 16, 0xFFFF0FFF, 0x00008000 }, - { GP7_15, 16, 0xFFFFF0FF, 0x00000800 }, - - { GP8_2 , 3 , 0xF0FFFFFF, 0x04000000 }, - { GP8_3 , 3 , 0xFF0FFFFF, 0x00400000 }, - { GP8_5 , 3 , 0xFFFF0FFF, 0x00004000 }, - { GP8_6 , 3 , 0xFFFFF0FF, 0x00000400 }, - { GP8_8 , 19, 0xFFFFFF0F, 0x00000080 }, - { GP8_9 , 19, 0xFFFFFFF0, 0x00000008 }, - { GP8_10, 18, 0x0FFFFFFF, 0x80000000 }, - { GP8_11, 18, 0xF0FFFFFF, 0x08000000 }, - { GP8_12, 18, 0xFF0FFFFF, 0x00800000 }, - { GP8_13, 18, 0xFFF0FFFF, 0x00080000 }, - { GP8_14, 18, 0xFFFF0FFF, 0x00008000 }, - { GP8_15, 18, 0xFFFFF0FF, 0x00000800 }, - - - { UART0_TXD, 3, 0xFF0FFFFF, 0x00200000 }, - { UART0_RXD, 3, 0xFFF0FFFF, 0x00020000 }, - - { UART1_TXD, 4, 0x0FFFFFFF, 0x20000000 }, - { UART1_RXD, 4, 0xF0FFFFFF, 0x02000000 }, - - { SPI0_MOSI, 3, 0xFFFF0FFF, 0x00001000 }, - { SPI0_MISO, 3, 0xFFFFF0FF, 0x00000100 }, - { SPI0_SCL, 3, 0xFFFFFFF0, 0x00000001 }, - { SPI0_CS, 3, 0xF0FFFFFF, 0x01000000 }, - - { SPI1_MOSI, 5, 0xFF0FFFFF, 0x00100000 }, - { SPI1_MISO, 5, 0xFFF0FFFF, 0x00010000 }, - { SPI1_SCL, 5, 0xFFFFF0FF, 0x00000100 }, - { SPI1_CS, 5, 0xFFFF0FFF, 0x00008000 }, - - { EPWM1A, 5, 0xFFFFFFF0, 0x00000002 }, - { EPWM1B, 5, 0xFFFFFF0F, 0x00000020 }, - { APWM0, 2, 0x0FFFFFFF, 0x20000000 }, - { APWM1, 1, 0x0FFFFFFF, 0x40000000 }, - { EPWM0B, 3, 0xFFFFFF0F, 0x00000020 }, - - { AXR3, 2, 0xFFF0FFFF, 0x00010000 }, - { AXR4, 2, 0xFFFF0FFF, 0x00001000 }, - - {-1 } -}; - -typedef struct gpio_controller *__iomem GPIOC; - -typedef struct -{ - int Pin; // GPIO pin number - GPIOC pGpio; // GPIO bank base address - u32 Mask; // GPIO pin mask -} -INPIN; - -#define REGUnlock {\ - iowrite32(0x83E70B13,da8xx_syscfg0_base + 0x38);\ - iowrite32(0x95A4F1E0,da8xx_syscfg0_base + 0x3C);\ - } - -#define REGLock {\ - iowrite32(0x00000000,da8xx_syscfg0_base + 0x38);\ - iowrite32(0x00000000,da8xx_syscfg0_base + 0x3C);\ - } - - - - -#else - -extern MRM MuxRegMap[]; - -#endif /* AM1808_H_ */ - - diff --git a/brick/kernel/source/bytecodes.h b/brick/kernel/source/bytecodes.h deleted file mode 100644 index af1640c8..00000000 --- a/brick/kernel/source/bytecodes.h +++ /dev/null @@ -1,1744 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * As a special exception, if other files instantiate templates or use macros or - * inline functions from this file, or you compile this file and link it with - * other works to produce a work based on this file, this file does not by itself - * cause the resulting work to be covered by the GNU General Public License. - * However the source code for this file must still be made available in accordance - * with section (3) of the GNU General Public License. - * - */ - - -#ifndef BYTECODES_H_ -#define BYTECODES_H_ - -#define BYTECODE_VERSION 1.09 - -/*! \page system - * - * \verbatim - */ - -// HARDWARE - -#define vmOUTPUTS 4 //!< Number of output ports in the system -#define vmINPUTS 4 //!< Number of input ports in the system -#define vmBUTTONS 6 //!< Number of buttons in the system -#define vmLEDS 4 //!< Number of LEDs in the system - -#define vmLCD_WIDTH 178 //!< LCD horizontal pixels -#define vmLCD_HEIGHT 128 //!< LCD vertical pixels -#define vmTOPLINE_HEIGHT 10 //!< Top line vertical pixels -#define vmLCD_STORE_LEVELS 3 //!< Store levels - -#define vmDEFAULT_VOLUME 100 -#define vmDEFAULT_SLEEPMINUTES 30 - -// SOFTWARE - -#define vmFG_COLOR 1 //!< Forground color -#define vmBG_COLOR 0 //!< Background color - -#define vmCHAIN_DEPT 4 //!< Number of bricks in the USB daisy chain (master + slaves) - -#define FILEPERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) -#define DIRPERMISSIONS (S_IRWXU | S_IRWXG | S_IRWXO) -#define SYSPERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) - -#define vmPATHSIZE 84 //!< Max path size excluding trailing forward slash including zero termination -#define vmNAMESIZE 32 //!< Max name size including zero termination (must be divideable by 4) -#define vmEXTSIZE 5 //!< Max extension size including dot and zero termination -#define vmFILENAMESIZE 120 //!< Max filename size including path, name, extension and termination (must be divideable by 4) -#define vmMACSIZE 18 //!< Max WIFI MAC size including zero termination -#define vmIPSIZE 16 //!< Max WIFI IP size including zero termination -#define vmBTADRSIZE 13 //!< Max bluetooth address size including zero termination - -#define vmERR_STRING_SIZE 32 // Inclusive zero termination - -#define vmEVENT_BT_PIN 1 -#define vmEVENT_BT_REQ_CONF 2 - -#define vmMAX_VALID_TYPE 101 //!< Highest valid device type - -// FOLDERS - -#define vmMEMORY_FOLDER "/mnt/ramdisk" //!< Folder for non volatile user programs/data -#define vmPROGRAM_FOLDER "../prjs/BrkProg_SAVE" //!< Folder for On Brick Programming programs -#define vmDATALOG_FOLDER "../prjs/BrkDL_SAVE" //!< Folder for On Brick Data log files -#define vmSDCARD_FOLDER "../prjs/SD_Card" //!< Folder for SD card mount -#define vmUSBSTICK_FOLDER "../prjs/USB_Stick" //!< Folder for USB stick mount - -#define vmPRJS_DIR "../prjs" //!< Project folder -#define vmAPPS_DIR "../apps" //!< Apps folder -#define vmTOOLS_DIR "../tools" //!< Tools folder -#define vmTMP_DIR "../tmp" //!< Temporary folder - -#define vmSETTINGS_DIR "../sys/settings" //!< Folder for non volatile settings - -#define vmDIR_DEEPT 127 //!< Max directory items allocated including "." and ".." - -// FILES USED IN APPLICATION - -#define vmLASTRUN_FILE_NAME "lastrun" //!< Last run filename -#define vmCALDATA_FILE_NAME "caldata" //!< Calibration data filename - -// FILES USED IN APPS - -#define vmSLEEP_FILE_NAME "Sleep" //!< File used in "Sleep" app to save status -#define vmVOLUME_FILE_NAME "Volume" //!< File used in "Volume" app to save status -#define vmWIFI_FILE_NAME "WiFi" //!< File used in "WiFi" app to save status -#define vmBLUETOOTH_FILE_NAME "Bluetooth" //!< File used in "Bluetooth" app to save status - -// EXTENSIONS - -#define vmEXT_SOUND ".rsf" //!< Robot Sound File -#define vmEXT_GRAPHICS ".rgf" //!< Robot Graphics File -#define vmEXT_BYTECODE ".rbf" //!< Robot Byte code File -#define vmEXT_TEXT ".rtf" //!< Robot Text File -#define vmEXT_DATALOG ".rdf" //!< Robot Datalog File -#define vmEXT_PROGRAM ".rpf" //!< Robot Program File -#define vmEXT_CONFIG ".rcf" //!< Robot Configuration File -#define vmEXT_ARCHIVE ".raf" //!< Robot Archive File - -// NAME LENGTHs - -#define vmBRICKNAMESIZE 120 //!< Brick name maximal size (including zero termination) -#define vmBTPASSKEYSIZE 7 //!< Bluetooth pass key size (including zero termination) -#define vmWIFIPASSKEYSIZE 33 //!< WiFi pass key size (including zero termination) - -// VALID CHARACTERS - -#define vmCHARSET_NAME 0x01 //!< Character set allowed in brick name and raw filenames -#define vmCHARSET_FILENAME 0x02 //!< Character set allowed in file names -#define vmCHARSET_BTPASSKEY 0x04 //!< Character set allowed in bluetooth pass key -#define vmCHARSET_WIFIPASSKEY 0x08 //!< Character set allowed in WiFi pass key -#define vmCHARSET_WIFISSID 0x10 //!< Character set allowed in WiFi ssid - -// NUMBER LIMITS - -#define vmDATA8_MIN (-127) //!< DATA8 negative limit -#define vmDATA8_MAX (127) //!< DATA8 positive limit -#define vmDATA16_MIN (-32767) //!< DATA16 negative limit -#define vmDATA16_MAX (32767) //!< DATA16 positive limit -#define vmDATA32_MIN (-2147483647) //!< DATA32 negative limit -#define vmDATA32_MAX (2147483647) //!< DATA32 positive limit -#define vmDATAF_MIN (-2147483647) //!< DATAF negative limit -#define vmDATAF_MAX (2147483647) //!< DATAF positive limit - -#define vmDATA8_NAN (0x80) -#define vmDATA16_NAN (0x8000) -#define vmDATA32_NAN (0x80000000) -#define vmDATAF_NAN (0x7FC00000) - -/* \endverbatim */ - -#define vmPULSE_GUI_BACKGROUND 0x01 -#define vmPULSE_BROWSER 0x02 -#define vmPULSE_KEY 0x04 - - - -/*! \page bytecodedef Byte Code Defines - * - * \verbatim - */ -typedef enum -{ -// \endverbatim \ref VM \verbatim -// 0000.... - opERROR = 0x00, // 0000 - opNOP = 0x01, // 0001 - opPROGRAM_STOP = 0x02, // 0010 - opPROGRAM_START = 0x03, // 0011 - opOBJECT_STOP = 0x04, // 0100 - opOBJECT_START = 0x05, // 0101 - opOBJECT_TRIG = 0x06, // 0110 - opOBJECT_WAIT = 0x07, // 0111 - opRETURN = 0x08, // 1000 - opCALL = 0x09, // 1001 - opOBJECT_END = 0x0A, // 1010 - opSLEEP = 0x0B, // 1011 - opPROGRAM_INFO = 0x0C, // 1100 - opLABEL = 0x0D, // 1101 - opPROBE = 0x0E, // 1110 - opDO = 0x0F, // 1111 - -// \endverbatim \ref cMath "MATH" \verbatim -// 0001.... -// ADD 00.. - opADD8 = 0x10, // 00 - opADD16 = 0x11, // 01 - opADD32 = 0x12, // 10 - opADDF = 0x13, // 11 -// SUB 01.. - opSUB8 = 0x14, // 00 - opSUB16 = 0x15, // 01 - opSUB32 = 0x16, // 10 - opSUBF = 0x17, // 11 -// MUL 10.. - opMUL8 = 0x18, // 00 - opMUL16 = 0x19, // 01 - opMUL32 = 0x1A, // 10 - opMULF = 0x1B, // 11 -// DIV 11.. - opDIV8 = 0x1C, // 00 - opDIV16 = 0x1D, // 01 - opDIV32 = 0x1E, // 10 - opDIVF = 0x1F, // 11 - -// \endverbatim \ref Logic "LOGIC" \verbatim -// LOGIC 0010.... -// OR 00.. - opOR8 = 0x20, // 00 - opOR16 = 0x21, // 01 - opOR32 = 0x22, // 10 - -// AND 01.. - opAND8 = 0x24, // 00 - opAND16 = 0x25, // 01 - opAND32 = 0x26, // 10 - -// XOR 10.. - opXOR8 = 0x28, // 00 - opXOR16 = 0x29, // 01 - opXOR32 = 0x2A, // 10 - -// RL 11.. - opRL8 = 0x2C, // 00 - opRL16 = 0x2D, // 01 - opRL32 = 0x2E, // 10 - -// \endverbatim \ref cMove "MOVE" \verbatim - opINIT_BYTES = 0x2F, // 1111 -// MOVE 0011.... -// MOVE8_ 00.. - opMOVE8_8 = 0x30, // 00 - opMOVE8_16 = 0x31, // 01 - opMOVE8_32 = 0x32, // 10 - opMOVE8_F = 0x33, // 11 -// MOVE16_ 01.. - opMOVE16_8 = 0x34, // 00 - opMOVE16_16 = 0x35, // 01 - opMOVE16_32 = 0x36, // 10 - opMOVE16_F = 0x37, // 11 -// MOVE32_ 10.. - opMOVE32_8 = 0x38, // 00 - opMOVE32_16 = 0x39, // 01 - opMOVE32_32 = 0x3A, // 10 - opMOVE32_F = 0x3B, // 11 -// MOVEF_ 11.. - opMOVEF_8 = 0x3C, // 00 - opMOVEF_16 = 0x3D, // 01 - opMOVEF_32 = 0x3E, // 10 - opMOVEF_F = 0x3F, // 11 - -// \endverbatim \ref cBranch "BRANCH" \verbatim -// BRANCH 010000.. - opJR = 0x40, // 00 - opJR_FALSE = 0x41, // 01 - opJR_TRUE = 0x42, // 10 - opJR_NAN = 0x43, // 11 - -// \endverbatim \ref cCompare "COMPARE" \verbatim -// COMPARE 010..... -// CP_LT 001.. - opCP_LT8 = 0x44, // 00 - opCP_LT16 = 0x45, // 01 - opCP_LT32 = 0x46, // 10 - opCP_LTF = 0x47, // 11 -// CP_GT 010.. - opCP_GT8 = 0x48, // 00 - opCP_GT16 = 0x49, // 01 - opCP_GT32 = 0x4A, // 10 - opCP_GTF = 0x4B, // 11 -// CP_EQ 011.. - opCP_EQ8 = 0x4C, // 00 - opCP_EQ16 = 0x4D, // 01 - opCP_EQ32 = 0x4E, // 10 - opCP_EQF = 0x4F, // 11 -// CP_NEQ 100.. - opCP_NEQ8 = 0x50, // 00 - opCP_NEQ16 = 0x51, // 01 - opCP_NEQ32 = 0x52, // 10 - opCP_NEQF = 0x53, // 11 -// CP_LTEQ 101.. - opCP_LTEQ8 = 0x54, // 00 - opCP_LTEQ16 = 0x55, // 01 - opCP_LTEQ32 = 0x56, // 10 - opCP_LTEQF = 0x57, // 11 -// CP_GTEQ 110.. - opCP_GTEQ8 = 0x58, // 00 - opCP_GTEQ16 = 0x59, // 01 - opCP_GTEQ32 = 0x5A, // 10 - opCP_GTEQF = 0x5B, // 11 - -// \endverbatim \ref Select "SELECT" \verbatim -// SELECT 010111.. - opSELECT8 = 0x5C, // 00 - opSELECT16 = 0x5D, // 01 - opSELECT32 = 0x5E, // 10 - opSELECTF = 0x5F, // 11 - - -// \endverbatim \ref VM \verbatim - opSYSTEM = 0x60, - opPORT_CNV_OUTPUT = 0x61, - opPORT_CNV_INPUT = 0x62, - opNOTE_TO_FREQ = 0x63, - -// \endverbatim \ref cBranch "BRANCH" \verbatim -// BRANCH 011000.. - //? 00 - //? 01 - //? 10 - //? 11 -// JR_LT 001.. - opJR_LT8 = 0x64, // 00 - opJR_LT16 = 0x65, // 01 - opJR_LT32 = 0x66, // 10 - opJR_LTF = 0x67, // 11 -// JR_GT 010.. - opJR_GT8 = 0x68, // 00 - opJR_GT16 = 0x69, // 01 - opJR_GT32 = 0x6A, // 10 - opJR_GTF = 0x6B, // 11 -// JR_EQ 011.. - opJR_EQ8 = 0x6C, // 00 - opJR_EQ16 = 0x6D, // 01 - opJR_EQ32 = 0x6E, // 10 - opJR_EQF = 0x6F, // 11 -// JR_NEQ 100.. - opJR_NEQ8 = 0x70, // 00 - opJR_NEQ16 = 0x71, // 01 - opJR_NEQ32 = 0x72, // 10 - opJR_NEQF = 0x73, // 11 -// JR_LTEQ 101.. - opJR_LTEQ8 = 0x74, // 00 - opJR_LTEQ16 = 0x75, // 01 - opJR_LTEQ32 = 0x76, // 10 - opJR_LTEQF = 0x77, // 11 -// JR_GTEQ 110.. - opJR_GTEQ8 = 0x78, // 00 - opJR_GTEQ16 = 0x79, // 01 - opJR_GTEQ32 = 0x7A, // 10 - opJR_GTEQF = 0x7B, // 11 - -// \endverbatim \ref VM \verbatim - opINFO = 0x7C, // 01111100 - opSTRINGS = 0x7D, // 01111101 - opMEMORY_WRITE = 0x7E, // 01111110 - opMEMORY_READ = 0x7F, // 01111111 - -// SYSTEM 1....... - -// \endverbatim \ref cUi "UI" \verbatim -// UI 100000.. - opUI_FLUSH = 0x80, // 00 - opUI_READ = 0x81, // 01 - opUI_WRITE = 0x82, // 10 - opUI_BUTTON = 0x83, // 11 - opUI_DRAW = 0x84, // 10000100 - -// \endverbatim \ref cTimer "TIMER" \verbatim - opTIMER_WAIT = 0x85, // 10000101 - opTIMER_READY = 0x86, // 10000110 - opTIMER_READ = 0x87, // 10000111 - -// \endverbatim \ref VM \verbatim -// BREAKPOINT 10001... - opBP0 = 0x88, // 000 - opBP1 = 0x89, // 001 - opBP2 = 0x8A, // 010 - opBP3 = 0x8B, // 011 - opBP_SET = 0x8C, // 10001100 - opMATH = 0x8D, // 10001101 - opRANDOM = 0x8E, // 10001110 - -// \endverbatim \ref cTimer "TIMER" \verbatim - opTIMER_READ_US = 0x8F, // 10001111 - -// \endverbatim \ref cUi "UI" \verbatim - opKEEP_ALIVE = 0x90, // 10010000 - -// \endverbatim \ref cCom "COM" \verbatim -// 100100 - opCOM_READ = 0x91, // 01 - opCOM_WRITE = 0x92, // 10 - -// \endverbatim \ref cSound "SOUND" \verbatim -// 100101 - opSOUND = 0x94, // 00 - opSOUND_TEST = 0x95, // 01 - opSOUND_READY = 0x96, // 10 - -// \endverbatim \ref cInput "INPUT" \verbatim -// - opINPUT_SAMPLE = 0x97, // 10010111 - -// 10011... - opINPUT_DEVICE_LIST = 0x98, // 000 - opINPUT_DEVICE = 0x99, // 001 - opINPUT_READ = 0x9A, // 010 - opINPUT_TEST = 0x9B, // 011 - opINPUT_READY = 0x9C, // 100 - opINPUT_READSI = 0x9D, // 101 - opINPUT_READEXT = 0x9E, // 110 - opINPUT_WRITE = 0x9F, // 111 -// \endverbatim \ref cOutput "OUTPUT" \verbatim -// 101..... - opOUTPUT_GET_TYPE = 0xA0, // 00000 - opOUTPUT_SET_TYPE = 0xA1, // 00001 - opOUTPUT_RESET = 0xA2, // 00010 - opOUTPUT_STOP = 0xA3, // 00011 - opOUTPUT_POWER = 0xA4, // 00100 - opOUTPUT_SPEED = 0xA5, // 00101 - opOUTPUT_START = 0xA6, // 00110 - opOUTPUT_POLARITY = 0xA7, // 00111 - opOUTPUT_READ = 0xA8, // 01000 - opOUTPUT_TEST = 0xA9, // 01001 - opOUTPUT_READY = 0xAA, // 01010 - opOUTPUT_POSITION = 0xAB, // 01011 - opOUTPUT_STEP_POWER = 0xAC, // 01100 - opOUTPUT_TIME_POWER = 0xAD, // 01101 - opOUTPUT_STEP_SPEED = 0xAE, // 01110 - opOUTPUT_TIME_SPEED = 0xAF, // 01111 - - opOUTPUT_STEP_SYNC = 0xB0, // 10000 - opOUTPUT_TIME_SYNC = 0xB1, // 10001 - opOUTPUT_CLR_COUNT = 0xB2, // 10010 - opOUTPUT_GET_COUNT = 0xB3, // 10011 - - opOUTPUT_PRG_STOP = 0xB4, // 10100 - -// \endverbatim \ref cMemory "MEMORY" \verbatim -// 11000... - opFILE = 0xC0, // 000 - opARRAY = 0xC1, // 001 - opARRAY_WRITE = 0xC2, // 010 - opARRAY_READ = 0xC3, // 011 - opARRAY_APPEND = 0xC4, // 100 - opMEMORY_USAGE = 0xC5, // 101 - opFILENAME = 0xC6, // 110 - -// \endverbatim \ref cMove "READ" \verbatim -// 110010.. - opREAD8 = 0xC8, // 00 - opREAD16 = 0xC9, // 01 - opREAD32 = 0xCA, // 10 - opREADF = 0xCB, // 11 - -// \endverbatim \ref cMove "WRITE" \verbatim -// 110011.. - opWRITE8 = 0xCC, // 00 - opWRITE16 = 0xCD, // 01 - opWRITE32 = 0xCE, // 10 - opWRITEF = 0xCF, // 11 - -// \endverbatim \ref cCom "COM" \verbatim -// 11010... - opCOM_READY = 0xD0, // 000 - opCOM_READDATA = 0xD1, // 001 - opCOM_WRITEDATA = 0xD2, // 010 - opCOM_GET = 0xD3, // 011 - opCOM_SET = 0xD4, // 100 - opCOM_TEST = 0xD5, // 101 - opCOM_REMOVE = 0xD6, // 110 - opCOM_WRITEFILE = 0xD7, // 111 - -// 11011... - opMAILBOX_OPEN = 0xD8, // 000 - opMAILBOX_WRITE = 0xD9, // 001 - opMAILBOX_READ = 0xDA, // 010 - opMAILBOX_TEST = 0xDB, // 011 - opMAILBOX_READY = 0xDC, // 100 - opMAILBOX_CLOSE = 0xDD, // 101 - -// SPARE 111..... - -// \endverbatim \ref TST \verbatim - opTST = 0xFF // 11111111 -} -OP; -/* - * \endverbatim - */ - - -//! \page uireadsubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - GET_VBATT = 1, - GET_IBATT = 2, - GET_OS_VERS = 3, - GET_EVENT = 4, - GET_TBATT = 5, - GET_IINT = 6, - GET_IMOTOR = 7, - GET_STRING = 8, - GET_HW_VERS = 9, - GET_FW_VERS = 10, - GET_FW_BUILD = 11, - GET_OS_BUILD = 12, - GET_ADDRESS = 13, - GET_CODE = 14, - KEY = 15, - GET_SHUTDOWN = 16, - GET_WARNING = 17, - GET_LBATT = 18, - TEXTBOX_READ = 21, - GET_VERSION = 26, - GET_IP = 27, - GET_POWER = 29, - GET_SDCARD = 30, - GET_USBSTICK = 31, - - UI_READ_SUBCODES -} -UI_READ_SUBCODE; - -//! \endverbatim - - -//! \page uiwritesubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - WRITE_FLUSH = 1, - FLOATVALUE = 2, - STAMP = 3, - PUT_STRING = 8, - VALUE8 = 9, - VALUE16 = 10, - VALUE32 = 11, - VALUEF = 12, - ADDRESS = 13, - CODE = 14, - DOWNLOAD_END = 15, - SCREEN_BLOCK = 16, - ALLOW_PULSE = 17, - SET_PULSE = 18, - TEXTBOX_APPEND = 21, - SET_BUSY = 22, - SET_TESTPIN = 24, - INIT_RUN = 25, - UPDATE_RUN = 26, - LED = 27, - POWER = 29, - GRAPH_SAMPLE = 30, - TERMINAL = 31, - - UI_WRITE_SUBCODES -} -UI_WRITE_SUBCODE; - -//! \endverbatim - - -//! \page uibuttonsubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - SHORTPRESS = 1, - LONGPRESS = 2, - WAIT_FOR_PRESS = 3, - FLUSH = 4, - PRESS = 5, - RELEASE = 6, - GET_HORZ = 7, - GET_VERT = 8, - PRESSED = 9, - SET_BACK_BLOCK = 10, - GET_BACK_BLOCK = 11, - TESTSHORTPRESS = 12, - TESTLONGPRESS = 13, - GET_BUMBED = 14, - GET_CLICK = 15, - - UI_BUTTON_SUBCODES -} -UI_BUTTON_SUBCODE; - -//! \endverbatim - - -//! \page comreadsubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - COMMAND = 14, - - COM_READ_SUBCODES -} -COM_READ_SUBCODE; - -//! \endverbatim - - -//! \page comwritesubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - REPLY = 14, - - COM_WRITE_SUBCODES -} -COM_WRITE_SUBCODE; - -//! \endverbatim - - -//! \page comgetsubcode Specific command parameter -//! -//! \verbatim -//! - -typedef enum -{ - GET_ON_OFF = 1, //!< Set, Get - GET_VISIBLE = 2, //!< Set, Get - GET_RESULT = 4, //!< Get - GET_PIN = 5, //!< Set, Get - SEARCH_ITEMS = 8, //!< Get - SEARCH_ITEM = 9, //!< Get - FAVOUR_ITEMS = 10, //!< Get - FAVOUR_ITEM = 11, //!< Get - GET_ID = 12, - GET_BRICKNAME = 13, - GET_NETWORK = 14, - GET_PRESENT = 15, - GET_ENCRYPT = 16, - CONNEC_ITEMS = 17, - CONNEC_ITEM = 18, - GET_INCOMING = 19, - GET_MODE2 = 20, - - COM_GET_SUBCODES -} -COM_GET_SUBCODE; - -//! \endverbatim - - -//! \page comsetsubcode Specific command parameter -//! -//! \verbatim -//! - -typedef enum -{ - SET_ON_OFF = 1, //!< Set, Get - SET_VISIBLE = 2, //!< Set, Get - SET_SEARCH = 3, //!< Set - SET_PIN = 5, //!< Set, Get - SET_PASSKEY = 6, //!< Set - SET_CONNECTION = 7, //!< Set - SET_BRICKNAME = 8, - SET_MOVEUP = 9, - SET_MOVEDOWN = 10, - SET_ENCRYPT = 11, - SET_SSID = 12, - SET_MODE2 = 13, - - COM_SET_SUBCODES -} -COM_SET_SUBCODE; - -//! \endverbatim - - -//! \page inputdevicesubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - INSERT_TYPE = 1, - GET_FORMAT = 2, - CAL_MINMAX = 3, - CAL_DEFAULT = 4, - GET_TYPEMODE = 5, - GET_SYMBOL = 6, - CAL_MIN = 7, - CAL_MAX = 8, - SETUP = 9, - CLR_ALL = 10, - GET_RAW = 11, - GET_CONNECTION = 12, - STOP_ALL = 13, - SET_TYPEMODE = 14, - READY_IIC = 15, - GET_NAME = 21, - GET_MODENAME = 22, - SET_RAW = 23, - GET_FIGURES = 24, - GET_CHANGES = 25, - CLR_CHANGES = 26, - READY_PCT = 27, - READY_RAW = 28, - READY_SI = 29, - GET_MINMAX = 30, - GET_BUMPS = 31, - - INPUT_DEVICESUBCODES -} -INPUT_DEVICE_SUBCODE; - -//! \endverbatim - - -//! \page programinfosubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - OBJ_STOP = 0, // VM - OBJ_START = 4, // VM - GET_STATUS = 22, // VM - GET_SPEED = 23, // VM - GET_PRGRESULT = 24, // VM - SET_INSTR = 25, // VM - - PROGRAM_INFO_SUBCODES, -} -PROGRAM_INFO_SUBCODE; - -//! \endverbatim - - -//! \page uidrawsubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - UPDATE = 0, - CLEAN = 1, - PIXEL = 2, - LINE = 3, - CIRCLE = 4, - TEXT = 5, - ICON = 6, - PICTURE = 7, - VALUE = 8, - FILLRECT = 9, - RECT = 10, - NOTIFICATION = 11, - QUESTION = 12, - KEYBOARD = 13, - BROWSE = 14, - VERTBAR = 15, - INVERSERECT = 16, - SELECT_FONT = 17, - TOPLINE = 18, - FILLWINDOW = 19, - SCROLL = 20, - DOTLINE = 21, - VIEW_VALUE = 22, - VIEW_UNIT = 23, - FILLCIRCLE = 24, - STORE = 25, - RESTORE = 26, - ICON_QUESTION = 27, - BMPFILE = 28, - POPUP = 29, - GRAPH_SETUP = 30, - GRAPH_DRAW = 31, - TEXTBOX = 32, - - UI_DRAW_SUBCODES -} -UI_DRAW_SUBCODE; - -//! \endverbatim - - -//! \page memoryfilesubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - OPEN_APPEND = 0, - OPEN_READ = 1, - OPEN_WRITE = 2, - READ_VALUE = 3, - WRITE_VALUE = 4, - READ_TEXT = 5, - WRITE_TEXT = 6, - CLOSE = 7, - LOAD_IMAGE = 8, - GET_HANDLE = 9, - MAKE_FOLDER = 10, - GET_POOL = 11, - SET_LOG_SYNC_TIME = 12, - GET_FOLDERS = 13, - GET_LOG_SYNC_TIME = 14, - GET_SUBFOLDER_NAME = 15, - WRITE_LOG = 16, - CLOSE_LOG = 17, - GET_IMAGE = 18, - GET_ITEM = 19, - GET_CACHE_FILES = 20, - PUT_CACHE_FILE = 21, - GET_CACHE_FILE = 22, - DEL_CACHE_FILE = 23, - DEL_SUBFOLDER = 24, - GET_LOG_NAME = 25, - - OPEN_LOG = 27, - READ_BYTES = 28, - WRITE_BYTES = 29, - REMOVE = 30, - MOVE = 31, - - FILE_SUBCODES -} -FILE_SUBCODE; - -//! \endverbatim - - -//! \page memoryarraysubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - DELETE = 0, - CREATE8 = 1, - CREATE16 = 2, - CREATE32 = 3, - CREATEF = 4, - RESIZE = 5, - FILL = 6, - COPY = 7, - INIT8 = 8, - INIT16 = 9, - INIT32 = 10, - INITF = 11, - SIZE = 12, - READ_CONTENT = 13, - WRITE_CONTENT = 14, - READ_SIZE = 15, - - ARRAY_SUBCODES -} -ARRAY_SUBCODE; - -//! \endverbatim - - -//! \page memoryfilenamesubcode Specific command parameter -//! -//! \verbatim -//! - -typedef enum -{ - EXIST = 16, //!< MUST BE GREATER OR EQUAL TO "ARRAY_SUBCODES" - TOTALSIZE = 17, - SPLIT = 18, - MERGE = 19, - CHECK = 20, - PACK = 21, - UNPACK = 22, - GET_FOLDERNAME = 23, - - FILENAME_SUBCODES -} -FILENAME_SUBCODE; - -//! \endverbatim - - -//! \page infosubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - SET_ERROR = 1, - GET_ERROR = 2, - ERRORTEXT = 3, - - GET_VOLUME = 4, - SET_VOLUME = 5, - GET_MINUTES = 6, - SET_MINUTES = 7, - - INFO_SUBCODES -} -INFO_SUBCODE; - -//! \endverbatim - - -//! \page soundsubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - BREAK = 0, - TONE = 1, - PLAY = 2, - REPEAT = 3, - SERVICE = 4, - - SOUND_SUBCODES -} -SOUND_SUBCODE; - -//! \endverbatim - - -//! \page stringsubcode Specific command parameter -//! -//! -//! \verbatim -//! - -typedef enum -{ - GET_SIZE = 1, // VM get string size - ADD = 2, // VM add two strings - COMPARE = 3, // VM compare two strings - DUPLICATE = 5, // VM duplicate one string to another - VALUE_TO_STRING = 6, - STRING_TO_VALUE = 7, - STRIP = 8, - NUMBER_TO_STRING = 9, - SUB = 10, - VALUE_FORMATTED = 11, - NUMBER_FORMATTED = 12, - - STRING_SUBCODES -} -STRING_SUBCODE; - -//! \endverbatim - - -/*! \page types - -
- -TYPE VALUES FOR BYTE CODES: -\n - \verbatim */ - -typedef enum -{ - MODE_KEEP = -1, //!< Mode value that won't change mode in byte codes (convenient place to define) - TYPE_KEEP = 0, //!< Type value that won't change type in byte codes - - // Types defined in "typedata.rcf" - TYPE_NXT_TOUCH = 1, //!< Device is NXT touch sensor - TYPE_NXT_LIGHT = 2, //!< Device is NXT light sensor - TYPE_NXT_SOUND = 3, //!< Device is NXT sound sensor - TYPE_NXT_COLOR = 4, //!< Device is NXT color sensor - TYPE_NXT_ULTRASONIC = 5, //!< Device is NXT ultra sonic sensor - TYPE_NXT_TEMPERATURE = 6, //!< Device is NXT temperature sensor - TYPE_TACHO = 7, //!< Device is EV3/NXT tacho motor - TYPE_MINITACHO = 8, //!< Device is EV3 mini tacho motor - TYPE_NEWTACHO = 9, //!< Device is EV3 new tacho motor - - TYPE_TOUCH = 16, //!< Device is EV3 touch sensor - - // Types defined in known EV3 digital devices - TYPE_COLOR = 29, //!< Device is EV3 color sensor - TYPE_ULTRASONIC = 30, //!< Device is EV3 ultra sonic sensor - TYPE_GYRO = 32, //!< Device is EV3 gyro sensor - TYPE_IR = 33, //!< Device is EV3 IR sensor - - // Type range reserved for third party devices - TYPE_THIRD_PARTY_START = 50, - TYPE_THIRD_PARTY_END = 98, - - // Special types - TYPE_ENERGYMETER = 99, //!< Device is energy meter - TYPE_IIC_UNKNOWN = 100, //!< Device type is not known yet - TYPE_NXT_TEST = 101, //!< Device is a NXT ADC test sensor - - TYPE_NXT_IIC = 123, //!< Device is NXT IIC sensor - TYPE_TERMINAL = 124, //!< Port is connected to a terminal - TYPE_UNKNOWN = 125, //!< Port not empty but type has not been determined - TYPE_NONE = 126, //!< Port empty or not available - TYPE_ERROR = 127, //!< Port not empty and type is invalid -} -TYPE; - - -/* \endverbatim */ - - -/*! \page programid Program ID's (Slots) - - \anchor prgid - - \verbatim */ - -typedef enum -{ - GUI_SLOT = 0, //!< Program slot reserved for executing the user interface - USER_SLOT = 1, //!< Program slot used to execute user projects, apps and tools - CMD_SLOT = 2, //!< Program slot used for direct commands coming from c_com - TERM_SLOT = 3, //!< Program slot used for direct commands coming from c_ui - DEBUG_SLOT = 4, //!< Program slot used to run the debug ui - - SLOTS, //!< Maximum slots supported by the VM - - // ONLY VALID IN opPROGRAM_STOP - CURRENT_SLOT = -1 -} -SLOT; - -/* \endverbatim */ - - -/*! \page buttons Button - - \verbatim */ - -typedef enum -{ - NO_BUTTON = 0, - UP_BUTTON = 1, - ENTER_BUTTON = 2, - DOWN_BUTTON = 3, - RIGHT_BUTTON = 4, - LEFT_BUTTON = 5, - BACK_BUTTON = 6, - ANY_BUTTON = 7, - - BUTTONTYPES = 8 -} -BUTTONTYPE; - -/* \endverbatim */ - - -/*! \page mathsubcode Specific command parameter - - \verbatim */ - -typedef enum -{ - EXP = 1, //!< e^x r = expf(x) - MOD = 2, //!< Modulo r = fmod(x,y) - FLOOR = 3, //!< Floor r = floor(x) - CEIL = 4, //!< Ceiling r = ceil(x) - ROUND = 5, //!< Round r = round(x) - ABS = 6, //!< Absolute r = fabs(x) - NEGATE = 7, //!< Negate r = 0.0 - x - SQRT = 8, //!< Squareroot r = sqrt(x) - LOG = 9, //!< Log r = log10(x) - LN = 10, //!< Ln r = log(x) - SIN = 11, //!< - COS = 12, //!< - TAN = 13, //!< - ASIN = 14, //!< - ACOS = 15, //!< - ATAN = 16, //!< - MOD8 = 17, //!< Modulo DATA8 r = x % y - MOD16 = 18, //!< Modulo DATA16 r = x % y - MOD32 = 19, //!< Modulo DATA32 r = x % y - POW = 20, //!< Exponent r = powf(x,y) - TRUNC = 21, //!< Truncate r = (float)((int)(x * pow(y))) / pow(y) - - MATHTYPES //!< Maximum number of math functions supported by the VM -} -MATHTYPE; - -/* \endverbatim */ - - -//! \page tstsubcode Specific command parameter -//! -//! \verbatim -//! - -typedef enum -{ - TST_OPEN = 10, //!< MUST BE GREATER OR EQUAL TO "INFO_SUBCODES" - TST_CLOSE = 11, - TST_READ_PINS = 12, - TST_WRITE_PINS = 13, - TST_READ_ADC = 14, - TST_WRITE_UART = 15, - TST_READ_UART = 16, - TST_ENABLE_UART = 17, - TST_DISABLE_UART = 18, - TST_ACCU_SWITCH = 19, - TST_BOOT_MODE2 = 20, - TST_POLL_MODE2 = 21, - TST_CLOSE_MODE2 = 22, - TST_RAM_CHECK = 23, - - TST_SUBCODES -} -TST_SUBCODE; - -//! \endverbatim - - -/*! \page browsers Browser Types Avaliable - - \verbatim */ - -typedef enum -{ - BROWSE_FOLDERS = 0, //!< Browser for folders - BROWSE_FOLDS_FILES = 1, //!< Browser for folders and files - BROWSE_CACHE = 2, //!< Browser for cached / recent files - BROWSE_FILES = 3, //!< Browser for files - - BROWSERTYPES //!< Maximum font types supported by the VM -} -BROWSERTYPE; - -/* \endverbatim */ - - -/*! \page fonts Font Types Avaliable - - \verbatim */ - -typedef enum -{ - NORMAL_FONT = 0, - SMALL_FONT = 1, - LARGE_FONT = 2, - TINY_FONT = 3, - - FONTTYPES //!< Maximum font types supported by the VM -} -FONTTYPE; - -/* \endverbatim */ - - -/*! \page icons Icon Types Avaliable - - \verbatim */ - -typedef enum -{ - NORMAL_ICON = 0, //!< "24x12_Files_Folders_Settings.bmp" - SMALL_ICON = 1, - LARGE_ICON = 2, //!< "24x22_Yes_No_OFF_FILEOps.bmp" - MENU_ICON = 3, - ARROW_ICON = 4, //!< "8x12_miniArrows.bmp" - - ICONTYPES //!< Maximum icon types supported by the VM -} -ICONTYPE; - - -typedef enum -{ - SICON_CHARGING = 0, - SICON_BATT_4 = 1, - SICON_BATT_3 = 2, - SICON_BATT_2 = 3, - SICON_BATT_1 = 4, - SICON_BATT_0 = 5, - SICON_WAIT1 = 6, - SICON_WAIT2 = 7, - SICON_BT_ON = 8, - SICON_BT_VISIBLE = 9, - SICON_BT_CONNECTED = 10, - SICON_BT_CONNVISIB = 11, - SICON_WIFI_3 = 12, - SICON_WIFI_2 = 13, - SICON_WIFI_1 = 14, - SICON_WIFI_CONNECTED = 15, - - SICON_USB = 21, - - S_ICON_NOS -} -S_ICON_NO; - - -typedef enum -{ - ICON_NONE = -1, - ICON_RUN = 0, - ICON_FOLDER = 1, - ICON_FOLDER2 = 2, - ICON_USB = 3, - ICON_SD = 4, - ICON_SOUND = 5, - ICON_IMAGE = 6, - ICON_SETTINGS = 7, - ICON_ONOFF = 8, - ICON_SEARCH = 9, - ICON_WIFI = 10, - ICON_CONNECTIONS = 11, - ICON_ADD_HIDDEN = 12, - ICON_TRASHBIN = 13, - ICON_VISIBILITY = 14, - ICON_KEY = 15, - ICON_CONNECT = 16, - ICON_DISCONNECT = 17, - ICON_UP = 18, - ICON_DOWN = 19, - ICON_WAIT1 = 20, - ICON_WAIT2 = 21, - ICON_BLUETOOTH = 22, - ICON_INFO = 23, - ICON_TEXT = 24, - - - ICON_QUESTIONMARK = 27, - ICON_INFO_FILE = 28, - ICON_DISC = 29, - ICON_CONNECTED = 30, - ICON_OBP = 31, - ICON_OBD = 32, - ICON_OPENFOLDER = 33, - ICON_BRICK1 = 34, - N_ICON_NOS -} -N_ICON_NO; - - -typedef enum -{ - YES_NOTSEL = 0, - YES_SEL = 1, - NO_NOTSEL = 2, - NO_SEL = 3, - OFF = 4, - WAIT_VERT = 5, - WAIT_HORZ = 6, - TO_MANUAL = 7, - WARNSIGN = 8, - WARN_BATT = 9, - WARN_POWER = 10, - WARN_TEMP = 11, - NO_USBSTICK = 12, - TO_EXECUTE = 13, - TO_BRICK = 14, - TO_SDCARD = 15, - TO_USBSTICK = 16, - TO_BLUETOOTH = 17, - TO_WIFI = 18, - TO_TRASH = 19, - TO_COPY = 20, - TO_FILE = 21, - CHAR_ERROR = 22, - COPY_ERROR = 23, - PROGRAM_ERROR = 24, - - - WARN_MEMORY = 27, - L_ICON_NOS -} -L_ICON_NO; - - -typedef enum -{ - ICON_STAR = 0, - ICON_LOCKSTAR = 1, - ICON_LOCK = 2, - ICON_PC = 3, //!< Bluetooth type PC - ICON_PHONE = 4, //!< Bluetooth type PHONE - ICON_BRICK = 5, //!< Bluetooth type BRICK - ICON_UNKNOWN = 6, //!< Bluetooth type UNKNOWN - ICON_FROM_FOLDER = 7, - ICON_CHECKBOX = 8, - ICON_CHECKED = 9, - ICON_XED = 10, - - M_ICON_NOS -} -M_ICON_NO; - - -typedef enum -{ - - ICON_LEFT = 1, - ICON_RIGHT = 2, - - A_ICON_NOS -} -A_ICON_NO; - - -/* \endverbatim */ - - -/*! \page bttypes Bluetooth Device Types - - \verbatim */ - -typedef enum -{ - BTTYPE_PC = 3, //!< Bluetooth type PC - BTTYPE_PHONE = 4, //!< Bluetooth type PHONE - BTTYPE_BRICK = 5, //!< Bluetooth type BRICK - BTTYPE_UNKNOWN = 6, //!< Bluetooth type UNKNOWN - - BTTYPES -} -BTTYPE; - - -/* \endverbatim */ - - -/*! \page ledpatterns LED Pattern - - \verbatim */ - -typedef enum -{ - LED_BLACK = 0, - LED_GREEN = 1, - LED_RED = 2, - LED_ORANGE = 3, - LED_GREEN_FLASH = 4, - LED_RED_FLASH = 5, - LED_ORANGE_FLASH = 6, - LED_GREEN_PULSE = 7, - LED_RED_PULSE = 8, - LED_ORANGE_PULSE = 9, - - LEDPATTERNS -} -LEDPATTERN; - - -/* \endverbatim */ - - -typedef enum -{ - LED_ALL = 0, //!< All LEDs - LED_RR = 1, //!< Right red - LED_RG = 2, //!< Right green - LED_LR = 3, //!< Left red - LED_LG = 4 //!< Left green -} -LEDTYPE; - - -/*! \page filetypes File Types Avaliable - - \verbatim */ - - -typedef enum -{ - FILETYPE_UNKNOWN = 0x00, - TYPE_FOLDER = 0x01, - TYPE_SOUND = 0x02, - TYPE_BYTECODE = 0x03, - TYPE_GRAPHICS = 0x04, - TYPE_DATALOG = 0x05, - TYPE_PROGRAM = 0x06, - TYPE_TEXT = 0x07, - TYPE_SDCARD = 0x10, - TYPE_USBSTICK = 0x20, - - FILETYPES, //!< Maximum icon types supported by the VM - - TYPE_RESTART_BROWSER = -1, - TYPE_REFRESH_BROWSER = -2 -} -FILETYPE; - -/* \endverbatim */ - - -/*! \page results Results - - Describes result from executing functions - - \verbatim */ - - -typedef enum -{ - OK = 0, //!< No errors to report - BUSY = 1, //!< Busy - try again - FAIL = 2, //!< Something failed - STOP = 4, //!< Stopped - START = 8 //!< Start -} -RESULT; - -/* \endverbatim */ - - -/*! \page formats - * - * Data formats used in device type formats - * \verbatim - */ - -typedef enum -{ - DATA_8 = 0x00, //!< DATA8 (don't change) - DATA_16 = 0x01, //!< DATA16 (don't change) - DATA_32 = 0x02, //!< DATA32 (don't change) - DATA_F = 0x03, //!< DATAF (don't change) - DATA_S = 0x04, //!< Zero terminated string - DATA_A = 0x05, //!< Array handle - - DATA_V = 0x07, //!< Variable type - - DATA_PCT = 0x10, //!< Percent (used in opINPUT_READEXT) - DATA_RAW = 0x12, //!< Raw (used in opINPUT_READEXT) - DATA_SI = 0x13, //!< SI unit (used in opINPUT_READEXT) - - DATA_FORMATS -} -DATA_FORMAT; - -/*\endverbatim - * - * \n - */ - - -/*! \page delimiters - * - * Delimiter codes used to define how data is separated in files - * \verbatim - */ - -typedef enum -{ - DEL_NONE = 0, //!< No delimiter at all - DEL_TAB = 1, //!< Use tab as delimiter - DEL_SPACE = 2, //!< Use space as delimiter - DEL_RETURN = 3, //!< Use return as delimiter - DEL_COLON = 4, //!< Use colon as delimiter - DEL_COMMA = 5, //!< Use comma as delimiter - DEL_LINEFEED = 6, //!< Use line feed as delimiter - DEL_CRLF = 7, //!< Use return+line feed as delimiter - - DELS -} -DEL; - -/*\endverbatim - * - * \n - */ - - -/*! \page transportlayers Hardware Transport Layer - - \verbatim */ - -typedef enum -{ - HW_USB = 1, - HW_BT = 2, - HW_WIFI = 3, - - HWTYPES -} -HWTYPE; - -/* \endverbatim */ - - -/*! \page encryptions Encryption Types - - \verbatim */ - -typedef enum -{ - ENCRYPT_NONE = 0, - ENCRYPT_WPA2 = 1, - - ENCRYPTS -} -ENCRYPT; - -/* \endverbatim */ - - -typedef enum -{ - RED = 0, - GREEN = 1, - BLUE = 2, - BLANK = 3, - COLORS -} -COLOR; - - -/* Constants related to color sensor value using */ -/* Color sensor as color detector */ -typedef enum -{ - BLACKCOLOR = 1, - BLUECOLOR = 2, - GREENCOLOR = 3, - YELLOWCOLOR = 4, - REDCOLOR = 5, - WHITECOLOR = 6 -} -NXTCOLOR; - - -/*! \page warnings WARNINGS - - \verbatim */ - -typedef enum -{ - WARNING_TEMP = 0x01, - WARNING_CURRENT = 0x02, - WARNING_VOLTAGE = 0x04, - WARNING_MEMORY = 0x08, - WARNING_DSPSTAT = 0x10, - WARNING_RAM = 0x20, - WARNING_BATTLOW = 0x40, - WARNING_BUSY = 0x80, - - WARNINGS = 0x3F -} -WARNING; - -/* \endverbatim */ - - -#define DATA8_NAN ((DATA8)(-128)) -#define DATA16_NAN ((DATA16)(-32768)) -#define DATA32_NAN ((DATA32)(0x80000000)) -#define DATAF_NAN ((float)0 / (float)0) //(0x7FC00000) - -#define DATA8_MIN vmDATA8_MIN -#define DATA8_MAX vmDATA8_MAX -#define DATA16_MIN vmDATA16_MIN -#define DATA16_MAX vmDATA16_MAX -#define DATA32_MIN vmDATA32_MIN -#define DATA32_MAX vmDATA32_MAX -#define DATAF_MIN vmDATAF_MIN -#define DATAF_MAX vmDATAF_MAX - - - - -/*! \enum OBJSTAT - * - * Values used to describe an object's status - */ -typedef enum -{ - RUNNING = 0x0010, //!< Object code is running - WAITING = 0x0020, //!< Object is waiting for final trigger - STOPPED = 0x0040, //!< Object is stopped or not triggered yet - HALTED = 0x0080, //!< Object is halted because a call is in progress -} -OBJSTAT; - - -/*! \page devicecommands - * - * Device commands used to control (UART sensors) devices - * \verbatim - */ - -typedef enum -{ - DEVCMD_RESET = 0x11, //!< UART device reset - DEVCMD_FIRE = 0x11, //!< UART device fire (ultrasonic) - DEVCMD_CHANNEL = 0x12, //!< UART device channel (IR seeker) - - DEVCMDS -} -DEVCMD; - -/*\endverbatim - * - * \n - */ - - -// GRAPHICS - -#define vmPOP3_ABS_X 16 // -#define vmPOP3_ABS_Y 50 // - -#define vmPOP3_ABS_WARN_ICON_X 64 -#define vmPOP3_ABS_WARN_ICON_X1 40 -#define vmPOP3_ABS_WARN_ICON_X2 72 -#define vmPOP3_ABS_WARN_ICON_X3 104 -#define vmPOP3_ABS_WARN_ICON_Y 60 -#define vmPOP3_ABS_WARN_SPEC_ICON_X 88 -#define vmPOP3_ABS_WARN_SPEC_ICON_Y 60 -#define vmPOP3_ABS_WARN_TEXT_X 80 -#define vmPOP3_ABS_WARN_TEXT_Y 68 -#define vmPOP3_ABS_WARN_YES_X 72 -#define vmPOP3_ABS_WARN_YES_Y 90 -#define vmPOP3_ABS_WARN_LINE_X 21 -#define vmPOP3_ABS_WARN_LINE_Y 89 -#define vmPOP3_ABS_WARN_LINE_ENDX 155 - - -#define LONGToBytes(_x) (UBYTE)((_x) & 0xFF),(UBYTE)((_x >> 8) & 0xFF),(UBYTE)((_x >> 16) & 0xFF),(UBYTE)((_x >> 24) & 0xFF) -#define WORDToBytes(_x) (UBYTE)((_x) & 0xFF),(UBYTE)((_x >> 8) & 0xFF) -#define BYTEToBytes(_x) (UBYTE)((_x) & 0xFF) - -#define PROGRAMHeader(VersionInfo,NumberOfObjects,GlobalBytes)\ - 'L','E','G','O',LONGToBytes(0),WORDToBytes((UWORD)(BYTECODE_VERSION * 100.0)),WORDToBytes(NumberOfObjects),LONGToBytes(GlobalBytes) - -#define VMTHREADHeader(OffsetToInstructions,LocalBytes)\ - LONGToBytes(OffsetToInstructions),0,0,0,0,LONGToBytes(LocalBytes) - -#define SUBCALLHeader(OffsetToInstructions,LocalBytes)\ - LONGToBytes(OffsetToInstructions),0,0,1,0,LONGToBytes(LocalBytes) - -#define BLOCKHeader(OffsetToInstructions,OwnerObjectId,TriggerCount)\ - LONGToBytes(OffsetToInstructions),WORDToBytes(OwnerObjectId),WORDToBytes(TriggerCount),LONGToBytes(0) - -// MACROS FOR PRIMITIVES AND SYSTEM CALLS - -#define PRIMPAR_SHORT 0x00 -#define PRIMPAR_LONG 0x80 - -#define PRIMPAR_CONST 0x00 -#define PRIMPAR_VARIABEL 0x40 -#define PRIMPAR_LOCAL 0x00 -#define PRIMPAR_GLOBAL 0x20 -#define PRIMPAR_HANDLE 0x10 -#define PRIMPAR_ADDR 0x08 - -#define PRIMPAR_INDEX 0x1F -#define PRIMPAR_CONST_SIGN 0x20 -#define PRIMPAR_VALUE 0x3F - -#define PRIMPAR_BYTES 0x07 - -#define PRIMPAR_STRING_OLD 0 -#define PRIMPAR_1_BYTE 1 -#define PRIMPAR_2_BYTES 2 -#define PRIMPAR_4_BYTES 3 -#define PRIMPAR_STRING 4 - -#define PRIMPAR_LABEL 0x20 - -#define HND(x) PRIMPAR_HANDLE | x -#define ADR(x) PRIMPAR_ADDR | x - -#define LCS (PRIMPAR_LONG | PRIMPAR_STRING) - -#define LAB1(v) (PRIMPAR_LONG | PRIMPAR_LABEL),(v & 0xFF) - -#define LC0(v) ((v & PRIMPAR_VALUE) | PRIMPAR_SHORT | PRIMPAR_CONST) -#define LC1(v) (PRIMPAR_LONG | PRIMPAR_CONST | PRIMPAR_1_BYTE),(v & 0xFF) -#define LC2(v) (PRIMPAR_LONG | PRIMPAR_CONST | PRIMPAR_2_BYTES),(v & 0xFF),((v >> 8) & 0xFF) -#define LC4(v) (PRIMPAR_LONG | PRIMPAR_CONST | PRIMPAR_4_BYTES),((ULONG)v & 0xFF),(((ULONG)v >> (ULONG)8) & 0xFF),(((ULONG)v >> (ULONG)16) & 0xFF),(((ULONG)v >> (ULONG)24) & 0xFF) - -#define LV0(i) ((i & PRIMPAR_INDEX) | PRIMPAR_SHORT | PRIMPAR_VARIABEL | PRIMPAR_LOCAL) -#define LV1(i) (PRIMPAR_LONG | PRIMPAR_VARIABEL | PRIMPAR_LOCAL | PRIMPAR_1_BYTE),(i & 0xFF) -#define LV2(i) (PRIMPAR_LONG | PRIMPAR_VARIABEL | PRIMPAR_LOCAL | PRIMPAR_2_BYTES),(i & 0xFF),((i >> 8) & 0xFF) -#define LV4(i) (PRIMPAR_LONG | PRIMPAR_VARIABEL | PRIMPAR_LOCAL | PRIMPAR_4_BYTES),(i & 0xFF),((i >> 8) & 0xFF),((i >> 16) & 0xFF),((i >> 24) & 0xFF) - -#define GV0(i) ((i & PRIMPAR_INDEX) | PRIMPAR_SHORT | PRIMPAR_VARIABEL | PRIMPAR_GLOBAL) -#define GV1(i) (PRIMPAR_LONG | PRIMPAR_VARIABEL | PRIMPAR_GLOBAL | PRIMPAR_1_BYTE),(i & 0xFF) -#define GV2(i) (PRIMPAR_LONG | PRIMPAR_VARIABEL | PRIMPAR_GLOBAL | PRIMPAR_2_BYTES),(i & 0xFF),((i >> 8) & 0xFF) -#define GV4(i) (PRIMPAR_LONG | PRIMPAR_VARIABEL | PRIMPAR_GLOBAL | PRIMPAR_4_BYTES),(i & 0xFF),((i >> 8) & 0xFF),((i >> 16) & 0xFF),((i >> 24) & 0xFF) - -// MACROS FOR SUB CALLS - - -#define CALLPAR_IN 0x80 -#define CALLPAR_OUT 0x40 - -#define CALLPAR_TYPE 0x07 -#define CALLPAR_DATA8 DATA_8 -#define CALLPAR_DATA16 DATA_16 -#define CALLPAR_DATA32 DATA_32 -#define CALLPAR_DATAF DATA_F -#define CALLPAR_STRING DATA_S - -#define IN_8 (CALLPAR_IN | CALLPAR_DATA8) -#define IN_16 (CALLPAR_IN | CALLPAR_DATA16) -#define IN_32 (CALLPAR_IN | CALLPAR_DATA32) -#define IN_F (CALLPAR_IN | CALLPAR_DATAF) -#define IN_S (CALLPAR_IN | CALLPAR_STRING) -#define OUT_8 (CALLPAR_OUT | CALLPAR_DATA8) -#define OUT_16 (CALLPAR_OUT | CALLPAR_DATA16) -#define OUT_32 (CALLPAR_OUT | CALLPAR_DATA32) -#define OUT_F (CALLPAR_OUT | CALLPAR_DATAF) -#define OUT_S (CALLPAR_OUT | CALLPAR_STRING) - -#define IO_8 IN_8 | OUT_8 -#define IO_16 IN_16 | OUT_16 -#define IO_32 IN_32 | OUT_32 -#define IO_F IN_F | OUT_F -#define IO_S IN_S | OUT_S - -#define IN_OUT_8 IO_8 -#define IN_OUT_16 IO_16 -#define IN_OUT_32 IO_32 -#define IN_OUT_F IO_F -#define IN_OUT_S IO_S - -#endif /* BYTECODES_H_ */ diff --git a/brick/kernel/source/c_branch.h b/brick/kernel/source/c_branch.h deleted file mode 100644 index 8543c516..00000000 --- a/brick/kernel/source/c_branch.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef C_BRANCH_H_ -#define C_BRANCH_H_ - -void cBranchJr(void); - -void cBranchJrFalse(void); - -void cBranchJrTrue(void); - -void cBranchJrNan(void); - -void cBranchJrLt8(void); - -void cBranchJrLt16(void); - -void cBranchJrLt32(void); - -void cBranchJrLtF(void); - -void cBranchJrGt8(void); - -void cBranchJrGt16(void); - -void cBranchJrGt32(void); - -void cBranchJrGtF(void); - -void cBranchJrLtEq8(void); - -void cBranchJrLtEq16(void); - -void cBranchJrLtEq32(void); - -void cBranchJrLtEqF(void); - -void cBranchJrGtEq8(void); - -void cBranchJrGtEq16(void); - -void cBranchJrGtEq32(void); - -void cBranchJrGtEqF(void); - -void cBranchJrEq8(void); - -void cBranchJrEq16(void); - -void cBranchJrEq32(void); - -void cBranchJrEqF(void); - -void cBranchJrNEq8(void); - -void cBranchJrNEq16(void); - -void cBranchJrNEq32(void); - -void cBranchJrNEqF(void); - -#endif /* C_BRANCH_H_ */ diff --git a/brick/kernel/source/c_compare.h b/brick/kernel/source/c_compare.h deleted file mode 100644 index 2f8740ab..00000000 --- a/brick/kernel/source/c_compare.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef C_COMPARE_H_ -#define C_COMPARE_H_ - -void cCompareLt8(void); - -void cCompareLt16(void); - -void cCompareLt32(void); - -void cCompareLtF(void); - -void cCompareGt8(void); - -void cCompareGt16(void); - -void cCompareGt32(void); - -void cCompareGtF(void); - -void cCompareEq8(void); - -void cCompareEq16(void); - -void cCompareEq32(void); - -void cCompareEqF(void); - -void cCompareNEq8(void); - -void cCompareNEq16(void); - -void cCompareNEq32(void); - -void cCompareNEqF(void); - -void cCompareLtEq8(void); - -void cCompareLtEq16(void); - -void cCompareLtEq32(void); - -void cCompareLtEqF(void); - -void cCompareGtEq8(void); - -void cCompareGtEq16(void); - -void cCompareGtEq32(void); - -void cCompareGtEqF(void); - -void cCompareSelect8(void); - -void cCompareSelect16(void); - -void cCompareSelect32(void); - -void cCompareSelectF(void); - -#endif /* C_COMPARE_H_ */ diff --git a/brick/kernel/source/c_math.h b/brick/kernel/source/c_math.h deleted file mode 100644 index d8aba73f..00000000 --- a/brick/kernel/source/c_math.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef C_MATH_H_ -#define C_MATH_H_ - -#define DegToRad(D) (D * 0.0174532925) - -#define RadToDeg(R) (R * 57.2957795) - - -void cMathAdd8(void); - -void cMathAdd16(void); - -void cMathAdd32(void); - -void cMathAddF(void); - -void cMathSub8(void); - -void cMathSub16(void); - -void cMathSub32(void); - -void cMathSubF(void); - -void cMathMul8(void); - -void cMathMul16(void); - -void cMathMul32(void); - -void cMathMulF(void); - -void cMathDiv8(void); - -void cMathDiv16(void); - -void cMathDiv32(void); - -void cMathDivF(void); - -void cMathOr8(void); - -void cMathOr16(void); - -void cMathOr32(void); - -void cMathAnd8(void); - -void cMathAnd16(void); - -void cMathAnd32(void); - -void cMathXor8(void); - -void cMathXor16(void); - -void cMathXor32(void); - -void cMathRl8(void); - -void cMathRl16(void); - -void cMathRl32(void); - -void cMath(void); - -#endif /* C_MATH_H_ */ diff --git a/brick/kernel/source/c_move.h b/brick/kernel/source/c_move.h deleted file mode 100644 index 01233695..00000000 --- a/brick/kernel/source/c_move.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef C_MOVE_H_ -#define C_MOVE_H_ - -void cMove8to8(void); - -void cMove8to16(void); - -void cMove8to32(void); - -void cMove8toF(void); - -void cMove16to8(void); - -void cMove16to16(void); - -void cMove16to32(void); - -void cMove16toF(void); - -void cMove32to8(void); - -void cMove32to16(void); - -void cMove32to32(void); - -void cMove32toF(void); - -void cMoveFto8(void); - -void cMoveFto16(void); - -void cMoveFto32(void); - -void cMoveFtoF(void); - -void cMoveInitBytes(void); - -void cMoveRead8(void); - -void cMoveRead16(void); - -void cMoveRead32(void); - -void cMoveReadF(void); - -void cMoveWrite8(void); - -void cMoveWrite16(void); - -void cMoveWrite32(void); - -void cMoveWriteF(void); - - -#endif /* C_MOVE_H_ */ diff --git a/brick/kernel/source/c_timer.h b/brick/kernel/source/c_timer.h deleted file mode 100644 index 809e0877..00000000 --- a/brick/kernel/source/c_timer.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef C_TIMER_H_ -#define C_TIMER_H_ - -#if (HARDWARE != SIMULATION) -ULONG cTimerGetuS(void); -ULONG cTimerGetmS(void); -#endif - -void cTimerWait(void); - -void cTimerReady(void); - -void cTimerRead(void); - -void cTimerReaduS(void); - -#endif /* C_TIMER_H_ */ diff --git a/brick/kernel/source/lms2012.h b/brick/kernel/source/lms2012.h deleted file mode 100755 index 72f0d691..00000000 --- a/brick/kernel/source/lms2012.h +++ /dev/null @@ -1,1566 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * As a special exception, if other files instantiate templates or use macros or - * inline functions from this file, or you compile this file and link it with - * other works to produce a work based on this file, this file does not by itself - * cause the resulting work to be covered by the GNU General Public License. - * However the source code for this file must still be made available in accordance - * with section (3) of the GNU General Public License. - * - */ - - -/*! \page debug Terminal Configuration - * - \verbatim - - -TERMINAL CONFIGURATION (in top of "lms2012.h") - -Normal release: DEBUG not defined, TERMINAL_ENABLED = 0, DEBUG_UART = 4 - -Printf working: DEBUG not defined, TERMINAL_ENABLED = 0, DEBUG_UART = 0 - -Development with debug messages: DEBUG defined, TERMINAL_ENABLED = 1, DEBUG_UART = 0 - -*/ - - -//#define DEBUG //!< When defined debug messages is output on standard I/O (d_uart is different) - -#define TERMINAL_ENABLED 0 //!< DEBUG terminal enabled (0 = disabled, 1 = enabled) -#define DEBUG_UART 4 //!< UART used for debug (0 = port1, 1 = port2, ... 4 = none) - - -/* \endverbatim */ - -//#define DEBUG_VM -//#define DEBUG_TRACE_TASK -//#define DEBUG_C_COM -//#define DEBUG_C_INPUT -//#define DEBUG_C_INPUT_DAISYCHAIN -//#define DEBUG_C_INPUT_DATALOG -//#define DEBUG_C_INPUT_FAST_DATALOG -//#define DEBUG_C_MEMORY -//#define DEBUG_C_MEMORY_LOG -//#define DEBUG_C_MEMORY_FILE -//#define DEBUG_C_MEMORY_LOW -//#define DEBUG_C_SOUND -//#define DEBUG_C_UI - -//#define DEBUG_D_ANALOG -//#define DEBUG_D_POWER -//#define DEBUG_D_UART -//#define DEBUG_D_UART_ERROR -//#define DEBUG_D_UI -//#define DEBUG_D_SOUND -//#define DEBUG_D_IIC -//#define DEBUG_D_USBDEV - -//#define ENABLE_TEST_ON_PORT4 - -//#define BUFPRINTSIZE 100000 -//#define REMEMBER_TO_ENABLE_SAVE_USER_DATA -//#define REMEMBER_TO_FIX_TYPEDATA - -//#define DEBUG_TRACE_USB_COMMAND -//#define DEBUG_TRACE_MODE_CHANGE -//#define DEBUG_TRACE_KEY -//#define DEBUG_TRACE_ANGLE -//#define DEBUG_TRACE_US -//#define DEBUG_TRACE_VM -//#define DEBUG_TRACE_DAISYCHAIN -//#define DEBUG_BYTECODE_TIME -//#define DEBUG_TRACE_FREEZE -//#define DEBUG_TRACE_FILENAME -//#define DEBUG_TRACE_IIC -//#define DEBUG_SDCARD -//#define DEBUG_USBSTICK -//#define DEBUG_VIRTUAL_BATT_TEMP -//#define DEBUG_TEMP_SHUTDOWN -//#define DEBUG_BACK_BLOCKED -//#define DEBUG_MEMORY_USAGE -#define DEBUG_RECHARGEABLE -#define ALLOW_DEBUG_PULSE - - - -#ifndef LMS2012_H_ -#define LMS2012_H_ - -// HARDWARE PLATFORM - -#define EP2 4 //!< Schematics revision D -#define FINALB 3 //!< Schematics revision B and C -#define FINAL 2 //!< Final prototype -#define SIMULATION 0 //!< LEGO digital simulation - -#define PLATFORM_START FINAL //!< Oldest supported hardware (older versions will use this) -#define PLATFORM_END EP2 //!< Newest supported hardware (newer versions will use this) - -// Will be removed when not used anymore -#define A4 -1 -#define EVALBOARD -2 -#define ONE2ONE 1 //!< First real size prototype - - -#ifdef LEGO_SIMULATION - #define HARDWARE SIMULATION -#else - -#ifndef HARDWARE - #define HARDWARE FINAL //!< Actual hardware platform (must be one of above) -#endif - -#endif - -// Support for module parameter "HwId" -// -// Readout File int PCB -// -// V1.00 10 10 MP (h = home, e = education) -// V0.50 05 5 EP3 -// V0.40 04 4 EP2 -// V0.30 03 3 EP1 (FINALB) (DEFAULT if file "HwId" not found) -// V0.20 02 2 FINAL - -#ifdef HW_ID_SUPPORT - -char *HwId = "03"; - -#define HWID (((HwId[0] - '0') * 10) + (HwId[1] - '0')) - -#endif - - -// FIRMWARE VARIANTS - -//#define OLDCALL //!< Don't use optimised sub calls -//#define DISABLE_PRU_UARTS //!< Don't use port 3 and 4 for UART sensors -//#define DISABLE_OLD_COLOR //!< Don't support NXT color sensor -//#define DISABLE_ADC //!< Don't use ADC (no clock EMC test) -//#define ADC_BITBANGING //!< Don't use SPI for a/d converter -//#define DISABLE_DAISYCHAIN -//#define DISABLE_DAISYCHAIN_COM_CALL -//#define DISABLE_FAST_DATALOG_BUFFER -//#define DISABLE_BUMBED -//#define LOG_ASCII -//#define DISABLE_FIQ_IIC -#define UART1_FAKE_INTERRUPT //!< Don't use real interrupt on UART1 (linux prompt) -//#define DISABLE_LOW_VOLTAGE //!< Don't shut down on low voltage -//#define ENABLE_HIGH_CURRENT //!< Don't shut down on high current -//#define DISABLE_LOW_MEMORY //!< Don't check low memory -//#define DISABLE_UART_DATA_ERROR //!< Don't reset UART sensor if timeout or crc error -#define DISABLE_PREEMPTED_VM //!< Don't run VM as preempted -//#define DISABLE_SDCARD_SUPPORT //!< Don't use SD card -#define DISABLE_USBSTICK_SUPPORT //!< Don't use USB stick -//#define ENABLE_PERFORMANCE_TEST //!< Show performance bar in the top line -//#define ENABLE_LOAD_TEST //!< Show integrated current in the top line -//#define ENABLE_MEMORY_TEST //!< Show used memory in the top line -//#define ENABLE_STATUS_TEST -//#define DISABLE_VIRTUAL_BATT_TEMP -//#define DISABLE_SOUND -//#define DISABLE_PAR_ALIGNMENT //!< Disable possibility to align sub call parameter types -//#define DISABLE_NEW_CALL_MUTEX //!< Disable smart object switching after return from non reentrant sub call (enables blocked thread call) -//#define DISABLE_SYSTEM_BYTECODE //!< Disable the use of opSYSTEM command -//#define DISABLE_FILENAME_CHECK //!< Disable "c_memory" filename check -//#define DISABLE_AD_WORD_PROTECT //!< Disable A/D word result protection -//#define DISABLE_UPDATE_DISASSEMBLY //!< Disable disassemble of running update commands -#define DISABLE_BLOCK_ALIAS_LOCALS //!< Disable change of block locals if sub call alias (parallelism) - -#define TESTDEVICE 3 - -#ifdef Linux_X86 -#define DISABLE_DAISYCHAIN -#define DISABLE_DAISYCHAIN_COM_CALL -#endif - -#ifndef PCASM -#include -#endif - -#include "lmstypes.h" -#include "bytecodes.h" - -// Hardware - -#define OUTPUTS vmOUTPUTS //!< Number of output ports in the system -#define INPUTS vmINPUTS //!< Number of input ports in the system -#define BUTTONS vmBUTTONS //!< Number of buttons in the system -#define LEDS vmLEDS //!< Number of LEDs in the system - -#define LCD_WIDTH vmLCD_WIDTH //!< LCD horizontal pixels -#define LCD_HEIGHT vmLCD_HEIGHT //!< LCD vertical pixels -#define TOPLINE_HEIGHT vmTOPLINE_HEIGHT //!< Top line vertical pixels -#define LCD_STORE_LEVELS vmLCD_STORE_LEVELS //!< Store levels - -// Software - -#define FG_COLOR vmFG_COLOR //!< Foreground color -#define BG_COLOR vmBG_COLOR //!< Background color - -#define CHAIN_DEPT vmCHAIN_DEPT //!< Number of bricks in the USB daisy chain (master + slaves) - -#define EVENT_BT_PIN vmEVENT_BT_PIN - -// Folders - -#define MEMORY_FOLDER vmMEMORY_FOLDER -#define PROGRAM_FOLDER vmPROGRAM_FOLDER -#define DATALOG_FOLDER vmDATALOG_FOLDER -#define SDCARD_FOLDER vmSDCARD_FOLDER -#define USBSTICK_FOLDER vmUSBSTICK_FOLDER - -// Files -#define DETAILS_FILE vmDETAILS_FILE //!< File containing firmware version - -// Extensions - -#define EXT_SOUND vmEXT_SOUND //!< Rudolf sound file -#define EXT_GRAPHICS vmEXT_GRAPHICS //!< Rudolf graphics file -#define EXT_BYTECODE vmEXT_BYTECODE //!< Rudolf byte code file -#define EXT_TEXT vmEXT_TEXT //!< Rudolf text file -#define EXT_DATALOG vmEXT_DATALOG //!< Rudolf datalog file -#define EXT_PROGRAM vmEXT_PROGRAM //!< Rudolf program byte code file -#define EXT_CONFIG vmEXT_CONFIG //!< rudolf configuration file - -/*! \page system System Configuration - * - *
- * - * Following defines sets the system configuration and limitations.\n - * Defines with preceding "vm" is visible for the byte code assembler\n - * - * \verbatim - */ - -#define PROJECT "LMS2012" -#define VERS 1.09 - -//#define RETAILVERS //!< Retail version -//#define EDUCATIONVERS //!< Education version -#define DEVELOPERVERS //!< Developer version (telnet with password) -//#define TESTVERS '1' //!< Minor version (not shown if less than ASCII zero) - - -#ifdef RETAILVERS - -#define SPECIALVERS 'H' -#define LEGO_BUNDLE_SEED_ID "9RNK8ZF528" -#define LEGO_BUNDLE_ID "com.lego.lms" - -#endif - -#ifdef EDUCATIONVERS - -#define SPECIALVERS 'E' -#define LEGO_BUNDLE_SEED_ID "9YZJD9MXPZ" -#define LEGO_BUNDLE_ID "com.lego.education.ev3" - -#endif - -#ifdef DEVELOPERVERS - -#define SPECIALVERS 'D' -#define LEGO_BUNDLE_SEED_ID "9RNK8ZF528" -#define LEGO_BUNDLE_ID "com.lego.lms" - -#endif - -#ifdef TESTVERS - -#define SPECIALVERS TESTVERS -#define LEGO_BUNDLE_SEED_ID "BA9Q76VTQG" -#define LEGO_BUNDLE_ID "com.lego.education.ev3" -/* -#define SPECIALVERS TESTVERS -#define LEGO_BUNDLE_SEED_ID "BA9Q76VTQG" -#define LEGO_BUNDLE_ID "com.lego.edu.ev3" - -#define SPECIALVERS TESTVERS -#define LEGO_BUNDLE_SEED_ID "BA9Q76VTQG" -#define LEGO_BUNDLE_ID "com.lego.education.ev3programming" -*/ -#endif - - -#define MAX_PROGRAMS SLOTS //!< Max number of programs (including UI and direct commands) running at a time -#define MAX_BREAKPOINTS 4 //!< Max number of breakpoints (opCODES depends on this value) -#define MAX_LABELS 32 //!< Max number of labels per program -#define MAX_DEVICE_TYPE 127 //!< Highest type number (positive) -#define MAX_VALID_TYPE vmMAX_VALID_TYPE //!< Highest valid type -#define MAX_DEVICE_MODES 8 //!< Max number of modes in one device -#define MAX_DEVICE_DATASETS 8 //!< Max number of data sets in one device -#define MAX_DEVICE_DATALENGTH 32 //!< Max device data length - -#define MAX_DEVICE_BUSY_TIME 1200 //!< Max number of mS a device can be busy when read - -#define MAX_DEVICE_TYPES ((MAX_DEVICE_TYPE + 1) * MAX_DEVICE_MODES)//!< Max number of different device types and modes (max type data list size) - -#define MAX_FRAMES_PER_SEC 10 //!< Max frames per second update in display - -#define CACHE_DEEPT 10 //!< Max number of programs cached (in RECENT FILES MENU) -#define MAX_HANDLES 500 //!< Max number of handles to memory pools and arrays in one program - -#define MAX_ARRAY_SIZE 1000000000 //!< Max array size -#define MIN_ARRAY_ELEMENTS 0 //!< Min elements in a DATA8 array - -#define INSTALLED_MEMORY 6000 //!< Flash allocated to hold user programs/data -#define LOW_MEMORY 500 //!< Low memory warning [KB] - -#define LOGBUFFER_SIZE 1000 //!< Min log buffer size -#define DEVICE_LOGBUF_SIZE 300 //!< Device log buffer size (black layer buffer) -#define MIN_LIVE_UPDATE_TIME 10 //!< [mS] Min sample time when live update - -#define MIN_IIC_REPEAT_TIME 10 //!< [mS] Min IIC device repeat time -#define MAX_IIC_REPEAT_TIME 1000 //!< [mS] Max IIC device repeat time - -#define MAX_COMMAND_BYTECODES 64 //!< Max number of byte codes in a debug terminal direct command -#define MAX_COMMAND_LOCALS 64 //!< Max number of bytes allocated for direct command local variables -#define MAX_COMMAND_GLOBALS 1021 //!< Max number of bytes allocated for direct command global variables - -#define UI_PRIORITY 20 //!< UI byte codes before switching VM thread -#define C_PRIORITY 200 //!< C call byte codes - -#ifndef DISABLE_PREEMPTED_VM -#define PRG_PRIORITY 2000 //!< Prg byte codes before switching VM thread -#else -#define PRG_PRIORITY 200 //!< Prg byte codes before switching VM thread -#endif - -#define BUTTON_DEBOUNCE_TIME 30 -#define BUTTON_START_REPEAT_TIME 400 -#define BUTTON_REPEAT_TIME 200 - -#define LONG_PRESS_TIME 3000 //!< [mS] Time pressed before long press recognised - -#define ADC_REF 5000 //!< [mV] maximal value on ADC -#define ADC_RES 4095 //!< [CNT] maximal count on ADC - -#define IN1_ID_HYSTERESIS 50 //!< [mV] half of the span one Id takes up on input connection 1 voltage -#define OUT5_ID_HYSTERESIS 100 //!< [mV] half of the span one Id takes up on output connection 5 voltage - -#define DEVICE_UPDATE_TIME 1000000 //!< Min device (sensor) update time [nS] -#define DELAY_TO_TYPEDATA 10000 //!< Time from daisy chain active to upload type data [mS] -#define DAISYCHAIN_MODE_TIME 10 //!< Time for daisy chain change mode [mS] -#define MAX_FILE_HANDLES 64 //!< Max number of down load file handles -#define MIN_HANDLE 3 //!< Min file handle to close - -#define ID_LENGTH 7 //!< Id length (BT MAC id) (incl. zero terminator) -#define NAME_LENGTH 12 //!< Name length (not including zero termination) - -#define ERROR_BUFFER_SIZE 8 //!< Number of errors in buffer - -#define PWM_DEVICE "lms_pwm" //!< PWM device name -#define PWM_DEVICE_NAME "/dev/lms_pwm" //!< PWM device file name - -#define MOTOR_DEVICE "lms_motor" //!< TACHO device name -#define MOTOR_DEVICE_NAME "/dev/lms_motor" //!< TACHO device file name - -#define ANALOG_DEVICE "lms_analog" //!< ANALOG device name -#define ANALOG_DEVICE_NAME "/dev/lms_analog" //!< ANALOG device file name - -#define POWER_DEVICE "lms_power" //!< POWER device name -#define POWER_DEVICE_NAME "/dev/lms_power" //!< POWER device file name - -#define DCM_DEVICE "lms_dcm" //!< DCM device name -#define DCM_DEVICE_NAME "/dev/lms_dcm" //!< DCM device file name - -#define UI_DEVICE "lms_ui" //!< UI device name -#define UI_DEVICE_NAME "/dev/lms_ui" //!< UI device file name - -#define LCD_DEVICE "lms_display" //!< DISPLAY device name -//#define LCD_DEVICE_NAME "/dev/lms_display" //!< DISPLAY device file name -#define LCD_DEVICE_NAME "/dev/fb0" //!< DISPLAY device file name - -#define UART_DEVICE "lms_uart" //!< UART device name -#define UART_DEVICE_NAME "/dev/lms_uart" //!< UART device file name - -#define USBDEV_DEVICE "lms_usbdev" //!< USB device -#define USBDEV_DEVICE_NAME "/dev/lms_usbdev" //!< USB device - -#define USBHOST_DEVICE "lms_usbhost" //!< USB host -#define USBHOST_DEVICE_NAME "/dev/lms_usbhost" //!< USB host - -#define SOUND_DEVICE "lms_sound" //!< SOUND device name -#define SOUND_DEVICE_NAME "/dev/lms_sound" //!< SOUND device - -#define IIC_DEVICE "lms_iic" //!< IIC device name -#define IIC_DEVICE_NAME "/dev/lms_iic" //!< IIC device - -#define BT_DEVICE "lms_bt" //!< BT device name -#define BT_DEVICE_NAME "/dev/lms_bt" //!< BT device - -#define UPDATE_DEVICE "lms_update" //!< UPDATE device name -#define UPDATE_DEVICE_NAME "/dev/lms_update" //!< UPDATE device - -#define TEST_PIN_DEVICE "lms_tst_pin" //!< TEST pin device name -#define TEST_PIN_DEVICE_NAME "/dev/lms_tst_pin" //!< TEST pin device file name - -#define TEST_UART_DEVICE "lms_tst_uart" //!< TEST UART device name -#define TEST_UART_DEVICE_NAME "/dev/lms_tst_uart" //!< TEST UART device file name - - -#define DIR_DEEPT vmDIR_DEEPT //!< Max directory items allocated - -// File - -//*********************************************************************************************************************** -//! \todo Filename sizes should only use vmPATHSIZE, vmNAMESIZE, vmEXTSIZE and vmFILENAMESIZE - -#define FILENAMESIZE vmFILENAMESIZE //!< All inclusive (path, filename, extension and zero termination) -#define FILENAME_SIZE 52 //!< User filename size without extension including zero -#define FOLDERNAME_SIZE 10 //!< Folder name size relative to "lms2012" folder including zero -#define SUBFOLDERNAME_SIZE FILENAME_SIZE //!< Sub folder name size without "/" including zero - -#define MAX_FILENAME_SIZE (FOLDERNAME_SIZE + SUBFOLDERNAME_SIZE + FILENAME_SIZE + 5) - -//*********************************************************************************************************************** - -#define TYPEDATE_FILE_NAME "typedata" //!< TypeData filename -#define ICON_FILE_NAME "icon" //!< Icon image filename -#define TEXT_FILE_NAME "text" //!< Text filename - -#define DEMO_FILE_NAME "../prjs/BrkProg_SAVE/Demo.rpf" - -// Memory - - - - - -// SD card - -#ifdef Linux_X86 -#define SDCARD_DEVICE1 "/dev/mmcblk0" -#define SDCARD_DEVICE2 "/dev/mmcblk0p1" -#else -#define SDCARD_DEVICE1 "/dev/mmcblk0" -#define SDCARD_DEVICE2 "/dev/mmcblk0p1" -#endif - -#define SDCARD_MOUNT "./mount_sdcard" -#define SDCARD_UNMOUNT "./unmount_sdcard" - -// USB stick - -#ifndef Linux_X86 -#define USBSTICK_DEVICE "/dev/sda" -#else -#define USBSTICK_DEVICE "/dev/sdf1" -#endif - -#define USBSTICK_MOUNT "./mount_usbstick" -#define USBSTICK_UNMOUNT "./unmount_usbstick" - -/* -#define DEFAULT_PRJS_FOLDER "~/lms2012/prjs" //!< Project folder name without trailing "/" -#define DEFAULT_APPS_FOLDER "~/lms2012/apps" //!< Applet folder name without trailing "/" -#define DEFAULT_TOOLS_FOLDER "~/lms2012/tools" //!< Setting folder name without trailing "/" -#define DEFAULT_SYS_FOLDER "~/lms2012/sys" //!< System folder name without trailing "/" -#define DEFAULT_SETUP_FOLDER "~/lms2012/sys" //!< Setup folder name without trailing "/" -#define DEFAULT_SD_FOLDER "~/lms2012/SD Card" //!< Sd card folder name without trailing "/" -#define DEFAULT_USB_FOLDER "~/lms2012/USB Memory"//!< USB Memory folder name without trailing "/" -*/ - -#define DEFAULT_FOLDER "ui" //!< Folder containing the first small programs -#define DEFAULT_UI "ui" //!< Default user interface - -#define DEFAULT_VOLUME vmDEFAULT_VOLUME -#define DEFAULT_SLEEPMINUTES vmDEFAULT_SLEEPMINUTES - -#define COM_CMD_DEVICE_NAME USBDEV_DEVICE_NAME //!< USB HID command pipe device file name - -/*! \endverbatim - * - */ - -/*! \page powermanagement Power Management - * - * This section describes various constants used in the power management - * - * - *\n - *
- * Battery Indicator - *\n - *
- * \verbatim - */ - -#define BATT_INDICATOR_HIGH 7500 //!< Battery indicator high [mV] -#define BATT_INDICATOR_LOW 6200 //!< Battery indicator low [mV] - -#define ACCU_INDICATOR_HIGH 7500 //!< Rechargeable battery indicator high [mV] -#define ACCU_INDICATOR_LOW 7100 //!< Rechargeable battery indicator low [mV] - -/*! \endverbatim - * \subpage pmbattind - *\n - *
- * Low Voltage Shutdown - *\n - *
- * \verbatim - */ - -#define LOW_VOLTAGE_SHUTDOWN_TIME 10000 //!< Time from shutdown lower limit to shutdown [mS] - -#define BATT_WARNING_HIGH 6.2 //!< Battery voltage warning upper limit [V] -#define BATT_WARNING_LOW 5.5 //!< Battery voltage warning lower limit [V] -#define BATT_SHUTDOWN_HIGH 5.5 //!< Battery voltage shutdown upper limit [V] -#define BATT_SHUTDOWN_LOW 4.5 //!< Battery voltage shutdown lower limit [V] - -#define ACCU_WARNING_HIGH 7.1 //!< Rechargeable battery voltage warning upper limit [V] -#define ACCU_WARNING_LOW 6.5 //!< Rechargeable battery voltage warning lower limit [V] -#define ACCU_SHUTDOWN_HIGH 6.5 //!< Rechargeable battery voltage shutdown upper limit [V] -#define ACCU_SHUTDOWN_LOW 6.0 //!< Rechargeable battery voltage shutdown lower limit [V] - - /*! \endverbatim - * \subpage pmbattsd - *\n - */ -#ifdef ENABLE_HIGH_CURRENT - /*! \page powermanagement - * - *
- * High Load Shutdown - *\n - *
- * \verbatim - */ - -#define LOAD_SHUTDOWN_FAIL 4.0 //!< Current limit for instantly shutdown [A] -#define LOAD_SHUTDOWN_HIGH 3.0 //!< Current limit for integrated current shutdown [A*S] -#define LOAD_BREAK_EVEN 1.75 //!< Current limit for integrated current break even [A*S] - -#define LOAD_SLOPE_UP 0.2 //!< Current slope when current is above break even [A/S] -#define LOAD_SLOPE_DOWN 0.1 //!< Current slope when current is below break even [A/S] - - /*! \endverbatim - * \subpage pmloadsd - *\n - */ -#endif - -#ifndef DISABLE_VIRTUAL_BATT_TEMP - /*! \page powermanagement - * - *
- * High Temperature Shutdown - *\n - *
- * \verbatim - */ - -#define TEMP_SHUTDOWN_FAIL 45.0 //!< Temperature rise before fail shutdown [C] -#define TEMP_SHUTDOWN_WARNING 40.0 //!< Temperature rise before warning [C] - - /*! \endverbatim - * \subpage pmtempsd - *\n - */ -#endif - -#define UPDATE_TIME1 2 //!< Update repeat time1 [mS] -#define UPDATE_TIME2 10 //!< Update repeat time2 [mS] -#define UPDATE_MEMORY 200 //!< Update memory size [mS] -#define UPDATE_SDCARD 500 //!< Update sdcard size [mS] -#define UPDATE_USBSTICK 500 //!< Update usbstick size [mS] - - -// Per start of (polution) defines -#define MAX_SOUND_DATA_SIZE 250 -#define SOUND_CHUNK 250 -#define SOUND_ADPCM_CHUNK 125 -#define SOUND_MASTER_CLOCK 132000000 -#define SOUND_TONE_MASTER_CLOCK 1031250 -#define SOUND_MIN_FRQ 250 -#define SOUND_MAX_FRQ 10000 -#define SOUND_MAX_LEVEL 8 -#define SOUND_FILE_BUFFER_SIZE SOUND_CHUNK + 2 // 12.8 mS @ 8KHz -#define SOUND_BUFFER_COUNT 3 -#define SOUND_FILE_FORMAT_NORMAL 0x0100 // RSO-file -#define SOUND_FILE_FORMAT_COMPRESSED 0x0101 // RSO-file compressed -// Per end of defines - - -/*! - * - * \n - */ - - -#define VtoC(V) ((UWORD)((V * ADC_RES) / ADC_REF)) -#define CtoV(C) ((UWORD)((C * ADC_REF) / ADC_RES)) -#define MtoV(M) ((UWORD)((M * ADC_REF * 100) / (ADC_RES * 52))) - -#define KB 1024 - -enum -{ - FALSE = 0, - TRUE = 1, -}; - - -/*! \page connections Connections - * - * \anchor connectiontypes - * - * Following defines sets the input and output port connection type\n - * - * These connection types are evaluated in the DCM driver \ref DcmDriver "Device Detection Manager Driver" - * - * \verbatim - */ - -typedef enum -{ - CONN_UNKNOWN = 111, //!< Connection is fake (test) - - CONN_DAISYCHAIN = 117, //!< Connection is daisy chained - CONN_NXT_COLOR = 118, //!< Connection type is NXT color sensor - CONN_NXT_DUMB = 119, //!< Connection type is NXT analog sensor - CONN_NXT_IIC = 120, //!< Connection type is NXT IIC sensor - - CONN_INPUT_DUMB = 121, //!< Connection type is LMS2012 input device with ID resistor - CONN_INPUT_UART = 122, //!< Connection type is LMS2012 UART sensor - - CONN_OUTPUT_DUMB = 123, //!< Connection type is LMS2012 output device with ID resistor - CONN_OUTPUT_INTELLIGENT = 124, //!< Connection type is LMS2012 output device with communication - CONN_OUTPUT_TACHO = 125, //!< Connection type is LMS2012 tacho motor with series ID resistance - - CONN_NONE = 126, //!< Port empty or not available - CONN_ERROR = 127, //!< Port not empty and type is invalid -} -CONN; - -/*\endverbatim - * - * \n - */ - - - -/*! \page objectstatus Object Status - * -\verbatim - -Image load -> Initialize all objects - - -Initialize -> if TriggerCount == 0 -> RUNNING (VMTHREAD) - else -> STOPPED (waiting for 1. trigger) - -1.Trigger -> Initialise -> WAITING - -Triggered -> Enqueue -> RUNNING - -Done -> Dequeue -> STOPPED - - -Program start - | - v - STOPPED -------> WAITING -------> RUNNING --------, - ^ 1.trig/ n.trig/ done/ | - | Reset+Enqueue Dequeue | - | | - '----------------------------------------------' - -\endverbatim - */ - - -/*! \enum DSPSTAT - * - * Dispatch status values - */ -typedef enum -{ - NOBREAK = 0x0100, //!< Dispatcher running (looping) - STOPBREAK = 0x0200, //!< Break because of program stop - SLEEPBREAK = 0x0400, //!< Break because of sleeping - INSTRBREAK = 0x0800, //!< Break because of opcode break - BUSYBREAK = 0x1000, //!< Break because of waiting for completion - PRGBREAK = 0x2000, //!< Break because of program break - USERBREAK = 0x4000, //!< Break because of user decision - FAILBREAK = 0x8000 //!< Break because of fail -} -DSPSTAT; - -typedef void (*PRIM)(void); //!< Prototype for all byte codes - - - -/*! \page memorylayout Memory Layout - * - * RAM layout - * - *- GlobalVariables (aligned) - * - *- ObjectPointerList (aligned) - * - *- OBJ (aligned) - * - Ip (4 bytes) - * - Status (2 bytes) - * - TriggerCount/CallerId (2 bytes) - * - Local (0..MAX Bytes)\n - * - */ - -/*! \struct OBJ - * Object data is used to hold the variables used for an object (allocated at image load time) - */ -typedef struct // Object -{ - IP Ip; //!< Object instruction pointer - LP pLocal; //!< Local variable pointer -#ifndef DISABLE_NEW_CALL_MUTEX - UBYTE ObjStatus; //!< Object status - UBYTE Blocked; -#else - UWORD ObjStatus; //!< Object status -#endif - union //!< Different meaning for SUBCALL and BLOCKS - { - OBJID CallerId; //!< Caller id used for SUBCALL to save object id to return to - TRIGGER TriggerCount; //!< Trigger count used by BLOCK's trigger logic - }u; - VARDATA Local[]; //!< Poll of bytes used for local variables -} -OBJ; - - -/*! \struct BRKP - * Breakpoint data hold information used for breakpoint - */ -typedef struct -{ - IMINDEX Addr; //!< Offset to breakpoint address from image start - OP OpCode; //!< Saved substituted opcode -} -BRKP; - -/*! \struct PRG - * Program data hold information about a program - */ -typedef struct -{ - ULONG InstrCnt; //!< Instruction counter used for performance analyses - ULONG InstrTime; //!< Instruction time used for performance analyses - - ULONG StartTime; //!< Program start time [mS] - ULONG RunTime; //!< Program run time [uS] - - IP pImage; //!< Pointer to start of image - GP pData; //!< Pointer to start of data - GP pGlobal; //!< Pointer to start of global bytes - OBJHEAD* pObjHead; //!< Pointer to start of object headers - OBJ** pObjList; //!< Pointer to object pointer list - IP ObjectIp; //!< Working object Ip - LP ObjectLocal; //!< Working object locals - - OBJID Objects; //!< No of objects in image - OBJID ObjectId; //!< Active object id - - OBJSTAT Status; //!< Program status - OBJSTAT StatusChange; //!< Program status change - RESULT Result; //!< Program result (OK, BUSY, FAIL) - - BRKP Brkp[MAX_BREAKPOINTS]; //!< Storage for breakpoint logic - - LABEL Label[MAX_LABELS]; //!< Storage for labels - UWORD Debug; //!< Debug flag - - DATA8 Name[FILENAME_SIZE]; - -} -PRG; - - -#define TYPE_NAME_LENGTH 11 -#define SYMBOL_LENGTH 4 //!< Symbol leng th (not including zero) - -/*! \struct TYPES - * Device type data - */ -typedef struct // if data type changes - remember to change "cInputTypeDataInit" ! -{ - SBYTE Name[TYPE_NAME_LENGTH + 1]; //!< Device name - DATA8 Type; //!< Device type - DATA8 Connection; - DATA8 Mode; //!< Device mode - DATA8 DataSets; - DATA8 Format; - DATA8 Figures; - DATA8 Decimals; - DATA8 Views; - DATAF RawMin; //!< Raw minimum value (e.c. 0.0) - DATAF RawMax; //!< Raw maximum value (e.c. 1023.0) - DATAF PctMin; //!< Percent minimum value (e.c. -100.0) - DATAF PctMax; //!< Percent maximum value (e.c. 100.0) - DATAF SiMin; //!< SI unit minimum value (e.c. -100.0) - DATAF SiMax; //!< SI unit maximum value (e.c. 100.0) - UWORD InvalidTime; //!< mS from type change to valid data - UWORD IdValue; //!< Device id value (e.c. 0 ~ UART) - DATA8 Pins; //!< Device pin setup - SBYTE Symbol[SYMBOL_LENGTH + 1]; //!< SI unit symbol - UWORD Align; -} -TYPES; - -#define TYPE_PARAMETERS 19 //!< Number of members in the structure above -#define MAX_DEVICE_INFOLENGTH 54 //!< Number of bytes in the structure above (can not be changed) - - -/*!\enum ERR - * - * Describes error numbers - */ -typedef enum -{ - TOO_MANY_ERRORS_TO_BUFFER, - TYPEDATA_TABEL_FULL, - TYPEDATA_FILE_NOT_FOUND, - ANALOG_DEVICE_FILE_NOT_FOUND, - ANALOG_SHARED_MEMORY, - UART_DEVICE_FILE_NOT_FOUND, - UART_SHARED_MEMORY, - IIC_DEVICE_FILE_NOT_FOUND, - IIC_SHARED_MEMORY, - DISPLAY_SHARED_MEMORY, - UI_SHARED_MEMORY, - UI_DEVICE_FILE_NOT_FOUND, - LCD_DEVICE_FILE_NOT_FOUND, - OUTPUT_SHARED_MEMORY, - COM_COULD_NOT_OPEN_FILE, - COM_NAME_TOO_SHORT, - COM_NAME_TOO_LONG, - COM_INTERNAL, - VM_INTERNAL, - VM_PROGRAM_VALIDATION, - VM_PROGRAM_NOT_STARTED, - VM_PROGRAM_FAIL_BREAK, - VM_PROGRAM_INSTRUCTION_BREAK, - VM_PROGRAM_NOT_FOUND, - SOUND_DEVICE_FILE_NOT_FOUND, - SOUND_SHARED_MEMORY, - FILE_OPEN_ERROR, - FILE_READ_ERROR, - FILE_WRITE_ERROR, - FILE_CLOSE_ERROR, - FILE_GET_HANDLE_ERROR, - FILE_NAME_ERROR, - USB_SHARED_MEMORY, - OUT_OF_MEMORY, - ERRORS -} -ERR; - -// INTERFACE FOR SHARED LIBRARIES - -extern void PrimParAdvance(void); // Dummy get parameter - -extern void* PrimParPointer(void); // Get pointer to primitives and system calls parameters - -extern IP GetImageStart(void); // Get pointer to start of image - -extern void SetDispatchStatus(DSPSTAT Status); // Set dispatch status (result from executing byte code) - -extern void SetInstructions(ULONG Instructions); // Set number of instructions before VMThread change - -extern PRGID CurrentProgramId(void); // Get current program id - -extern OBJSTAT ProgramStatus(PRGID PrgId); // Get program status - -extern OBJSTAT ProgramStatusChange(PRGID PrgId); // Get program status change - -extern void ProgramEnd(PRGID PrgId); - -extern OBJID CallingObjectId(void); // Get calling objects id - -extern void AdjustObjectIp(IMOFFS Value); // Adjust IP - -extern IP GetObjectIp(void); // Get IP - -extern void SetObjectIp(IP Ip); // Set IP - -extern ULONG GetTimeUS(void); // Get uS - -extern ULONG GetTimeMS(void); // Get mS - -extern ULONG GetTime(void); // Get actual program time - -extern ULONG CurrentObjectIp(void); // Get current object ip - -extern void VmPrint(char *pString); // print string - -extern void SetTerminalEnable(DATA8 Value); // Terminal enable/disable - -extern DATA8 GetTerminalEnable(void); // Get terminal enable state - -extern void GetResourcePath(char *pString,DATA8 MaxLength);// Get resource path - -extern void* VmMemoryResize(HANDLER Handle,DATA32 Elements); - -extern void SetVolumePercent(DATA8 Volume); - -extern DATA8 GetVolumePercent(void); - -extern void SetSleepMinutes(DATA8 Minutes); - -extern DATA8 GetSleepMinutes(void); - -extern DSPSTAT ExecuteByteCode(IP pByteCode,GP pGlobals,LP pLocals); // Execute byte code stream (C-call) - -extern DATA8 CheckSdcard(DATA8 *pChanged,DATA32 *pTotal,DATA32 *pFree,DATA8 Force); - -extern DATA8 CheckUsbstick(DATA8 *pChanged,DATA32 *pTotal,DATA32 *pFree,DATA8 Force); - -extern void SetUiUpdate(void); - -extern RESULT ValidateChar(DATA8 *pChar,DATA8 Set); - -extern RESULT ValidateString(DATA8 *pString,DATA8 Set); - -extern ERR LogErrorGet(void); - -#ifdef BUFPRINTSIZE -extern void BufPrint(char Cmd,char *pFormat, ...); -#endif - - - -#define ERR_STRING_SIZE vmERR_STRING_SIZE // Inclusive zero termination - -extern void LogErrorNumber(ERR Error); // Log error number -extern DATA8 LogErrorNumberExists(ERR Error); - - -#ifndef DISABLE_OLD_COLOR - -#define COLORS 4 -#define CALPOINTS 3 - - -/*! \page NxtColorMemory - * - * Shared Memory - * - *
- * - * - * \verbatim - */ - -typedef struct -{ - ULONG Calibration[CALPOINTS][COLORS]; - UWORD CalLimits[CALPOINTS - 1]; - UWORD Crc; - UWORD ADRaw[COLORS]; - UWORD SensorRaw[COLORS]; -} -COLORSTRUCT; - -/*\endverbatim - * - * \n - */ - -#endif - - -// INTERFACE BETWEEN SHARED LIBRARIES AND MODULES - -/*! \page AnalogModuleMemory - * Shared Memory - * - *
- * - * It is possible to get a pointer to the raw analogue values for use in userspace - * this pointer will point to a struct and the layout is following: - * - * \verbatim - */ - -typedef struct -{ - DATA16 InPin1[INPUTS]; //!< Analog value at input port connection 1 - DATA16 InPin6[INPUTS]; //!< Analog value at input port connection 6 - DATA16 OutPin5[OUTPUTS]; //!< Analog value at output port connection 5 - DATA16 BatteryTemp; //!< Battery temperature - DATA16 MotorCurrent; //!< Current flowing to motors - DATA16 BatteryCurrent; //!< Current flowing from the battery - DATA16 Cell123456; //!< Voltage at battery cell 1, 2, 3,4, 5, and 6 -#ifndef DISABLE_FAST_DATALOG_BUFFER - DATA16 Pin1[INPUTS][DEVICE_LOGBUF_SIZE]; //!< Raw value from analog device - DATA16 Pin6[INPUTS][DEVICE_LOGBUF_SIZE]; //!< Raw value from analog device - UWORD Actual[INPUTS]; - UWORD LogIn[INPUTS]; - UWORD LogOut[INPUTS]; -#endif -#ifndef DISABLE_OLD_COLOR - COLORSTRUCT NxtCol[INPUTS]; -#endif - DATA16 OutPin5Low[OUTPUTS]; //!< Analog value at output port connection 5 when connection 6 is low - - DATA8 Updated[INPUTS]; - - DATA8 InDcm[INPUTS]; //!< Input port device types - DATA8 InConn[INPUTS]; - - DATA8 OutDcm[OUTPUTS]; //!< Output port device types - DATA8 OutConn[OUTPUTS]; -#ifndef DISABLE_PREEMPTED_VM - UWORD PreemptMilliSeconds; -#endif -} -ANALOG; - -/*\endverbatim - * - * \n - */ - - -/*! \page UartModuleMemory - * - * Shared Memory - * - *
- * - * It is possible to get a pointer to the uart values for use in userspace - * this pointer will point to a struct and the layout is following: - * - * \verbatim - */ - -#define UART_DATA_LENGTH MAX_DEVICE_DATALENGTH -#define UART_BUFFER_SIZE 64 - -typedef struct -{ - TYPES TypeData[INPUTS][MAX_DEVICE_MODES]; //!< TypeData - -#ifndef DISABLE_FAST_DATALOG_BUFFER - UWORD Repeat[INPUTS][DEVICE_LOGBUF_SIZE]; - DATA8 Raw[INPUTS][DEVICE_LOGBUF_SIZE][UART_DATA_LENGTH]; //!< Raw value from UART device - UWORD Actual[INPUTS]; - UWORD LogIn[INPUTS]; -#else - DATA8 Raw[INPUTS][UART_DATA_LENGTH]; //!< Raw value from UART device -#endif - DATA8 Status[INPUTS]; //!< Status - DATA8 Output[INPUTS][UART_DATA_LENGTH]; //!< Bytes to UART device - DATA8 OutputLength[INPUTS]; -} -UART; - -/*\endverbatim - * - * \n - */ - - -#define UART_PORT_CHANGED 0x01 //!< Input port changed -#define UART_DATA_READY 0x08 //!< Data is ready -#define UART_WRITE_REQUEST 0x10 //!< Write request - - -typedef struct -{ - DATA8 Connection[INPUTS]; - DATA8 Type[INPUTS]; - DATA8 Mode[INPUTS]; -} -DEVCON; - - -typedef struct -{ - TYPES TypeData; - DATA8 Port; - DATA8 Mode; -} -UARTCTL; - -#define UART_SET_CONN _IOWR('u',0,DEVCON) -#define UART_READ_MODE_INFO _IOWR('u',1,UARTCTL) -#define UART_NACK_MODE_INFO _IOWR('u',2,UARTCTL) -#define UART_CLEAR_CHANGED _IOWR('u',3,UARTCTL) - - -/*! \page IicModuleMemory - * - * Shared Memory - * - *
- * - * It is possible to get a pointer to the iic values for use in userspace - * this pointer will point to a struct and the layout is following: - * - * \verbatim - */ - -#define IIC_DATA_LENGTH MAX_DEVICE_DATALENGTH -#define IIC_NAME_LENGTH 8 - -typedef struct -{ - TYPES TypeData[INPUTS][MAX_DEVICE_MODES]; //!< TypeData - -#ifndef DISABLE_FAST_DATALOG_BUFFER - UWORD Repeat[INPUTS][DEVICE_LOGBUF_SIZE]; - DATA8 Raw[INPUTS][DEVICE_LOGBUF_SIZE][IIC_DATA_LENGTH]; //!< Raw value from IIC device - UWORD Actual[INPUTS]; - UWORD LogIn[INPUTS]; -#else - DATA8 Raw[INPUTS][IIC_DATA_LENGTH]; //!< Raw value from IIC device -#endif - DATA8 Status[INPUTS]; //!< Status - DATA8 Changed[INPUTS]; - DATA8 Output[INPUTS][IIC_DATA_LENGTH]; //!< Bytes to IIC device - DATA8 OutputLength[INPUTS]; -} -IIC; - -/*\endverbatim - * - * \n - */ - - -#define IIC_PORT_CHANGED 0x01 //!< Input port changed -#define IIC_DATA_READY 0x08 //!< Data is ready -#define IIC_WRITE_REQUEST 0x10 //!< Write request - - -typedef struct -{ - TYPES TypeData; - DATA8 Port; - DATA8 Mode; -} -IICCTL; - - -typedef struct -{ - RESULT Result; - DATA8 Port; - DATA8 Repeat; - DATA16 Time; - DATA8 WrLng; - DATA8 WrData[IIC_DATA_LENGTH]; - DATA8 RdLng; - DATA8 RdData[IIC_DATA_LENGTH]; -} -IICDAT; - - -typedef struct -{ - DATA8 Port; - DATA16 Time; - DATA8 Type; - DATA8 Mode; - DATA8 Manufacturer[IIC_NAME_LENGTH + 1]; - DATA8 SensorType[IIC_NAME_LENGTH + 1]; - DATA8 SetupLng; - ULONG SetupString; - DATA8 PollLng; - ULONG PollString; - DATA8 ReadLng; -} -IICSTR; - - -#define IIC_SET_CONN _IOWR('i',2,DEVCON) -#define IIC_READ_TYPE_INFO _IOWR('i',3,IICCTL) -#define IIC_SETUP _IOWR('i',5,IICDAT) -#define IIC_SET _IOWR('i',6,IICSTR) - - - - -#define TST_PIN_LENGTH 8 - -typedef struct -{ - DATA8 Port; - DATA8 Length; - DATA8 String[TST_PIN_LENGTH + 1]; -} -TSTPIN; - -#define TST_PIN_ON _IOWR('t',1,TSTPIN) -#define TST_PIN_OFF _IOWR('t',2,TSTPIN) -#define TST_PIN_READ _IOWR('t',3,TSTPIN) -#define TST_PIN_WRITE _IOWR('t',4,TSTPIN) - - - - -#define TST_UART_LENGTH UART_BUFFER_SIZE - -typedef struct -{ - DATA32 Bitrate; - DATA8 Port; - DATA8 Length; - DATA8 String[TST_UART_LENGTH]; -} -TSTUART; - -#define TST_UART_ON _IOWR('t',5,TSTUART) -#define TST_UART_OFF _IOWR('t',6,TSTUART) -#define TST_UART_EN _IOWR('t',7,TSTUART) -#define TST_UART_DIS _IOWR('t',8,TSTUART) -#define TST_UART_READ _IOWR('t',9,TSTUART) -#define TST_UART_WRITE _IOWR('t',10,TSTUART) - - - - -/*! \page UiModuleMemory - * - * Shared Memory - * - *
- * - * It is possible to get a pointer to the ui button states for use in userspace - * this pointer will point to a struct and the layout is following: - * - * \verbatim - */ - -typedef struct -{ - DATA8 Pressed[BUTTONS]; //!< Pressed status -} -UI; - -/*\endverbatim - * - * \n - */ - - -#define LCD_BUFFER_SIZE (((LCD_WIDTH + 7) / 8) * LCD_HEIGHT) -#define LCD_TOPLINE_SIZE (((LCD_WIDTH + 7) / 8) * (TOPLINE_HEIGHT + 1)) - - -/*! \page DisplayModuleMemory - * - * Shared Memory - * - *
- * - * It is possible to get a pointer to the display memory for use in userspace - * this pointer will point to a frame buffer as follows: - * - * \verbatim - */ - -typedef struct -{ - UBYTE Lcd[LCD_BUFFER_SIZE]; -} -LCD; - -/*\endverbatim - * - * \n - */ - - -/*! \page SoundModuleMemory - * - * Shared Memory - * - *
- * - * It is possible to get a pointer to the sound ready flag for use in userspace - * this pointer will point to a struct and the layout is following: - * - * \verbatim - */ - -typedef struct -{ - DATA8 Status; //!< Status -} -SOUND; - -/*\endverbatim - * - * \n - */ - - -/*! \page UsbModuleMemory - * - * Shared Memory - * - *
- * - * It is possible to get a pointer to the USB Speed (FULL or HIGH) for use in userspace - * this pointer will point to a struct and the layout is following: - * - * \verbatim - */ - -enum { - FULL_SPEED, - HIGH_SPEED - }; - -typedef struct -{ - DATA8 Speed; -} -USB_SPEED; - -/*\endverbatim - * - * \n - */ - -/*! \page VmNonvolatileMemory - * - * VM non volatile Memory - * - *
- * - * This struct will be loaded at start up and save when closing down VM - * - * \verbatim - */ - -typedef struct -{ - DATA8 VolumePercent; //!< System default volume [0..100%] - DATA8 SleepMinutes; //!< System sleep [0..120min] (0 = ~) -} -NONVOL; - -/*\endverbatim - * - * \n - */ - - -/* - * Motor/OUTPUT Typedef - */ -typedef struct -{ - SLONG TachoCounts; - SBYTE Speed; - SLONG TachoSensor; -}MOTORDATA; - -typedef struct -{ - DATA8 Cmd; - DATA8 Nos; - DATA8 Power; - DATA32 Step1; - DATA32 Step2; - DATA32 Step3; - DATA8 Brake; -} STEPPOWER; - -typedef struct -{ - DATA8 Cmd; - DATA8 Nos; - DATA8 Power; - DATA32 Time1; - DATA32 Time2; - DATA32 Time3; - DATA8 Brake; -} TIMEPOWER; - -typedef struct -{ - DATA8 Cmd; - DATA8 Nos; - DATA8 Speed; - DATA32 Step1; - DATA32 Step2; - DATA32 Step3; - DATA8 Brake; -} STEPSPEED; - -typedef struct -{ - DATA8 Cmd; - DATA8 Nos; - DATA8 Speed; - DATA32 Time1; - DATA32 Time2; - DATA32 Time3; - DATA8 Brake; -} TIMESPEED; - -typedef struct -{ - DATA8 Cmd; - DATA8 Nos; - DATA8 Speed; - DATA16 Turn; - DATA32 Step; - DATA8 Brake; -} STEPSYNC; - -typedef struct -{ - DATA8 Cmd; - DATA8 Nos; - DATA8 Speed; - DATA16 Turn; - DATA32 Time; - DATA8 Brake; -} TIMESYNC; -/* - * End of Motor/OUTPUT Typedef - */ - - -#define PRINTBUFFERSIZE 160 - -typedef struct -{ - NONVOL NonVol; - DATA8 FirstProgram[MAX_FILENAME_SIZE]; - - char PrintBuffer[PRINTBUFFERSIZE + 1]; - DATA8 TerminalEnabled; - - PRGID FavouritePrg; - PRGID ProgramId; //!< Program id running - PRG Program[MAX_PROGRAMS]; //!< Program[0] is the UI byte codes running - - - ULONG InstrCnt; //!< Instruction counter (performance test) - IP pImage; //!< Pointer to start of image - GP pGlobal; //!< Pointer to start of global bytes - OBJHEAD* pObjHead; //!< Pointer to start of object headers - OBJ** pObjList; //!< Pointer to object pointer list - - IP ObjectIp; //!< Working object Ip - LP ObjectLocal; //!< Working object locals - OBJID Objects; //!< No of objects in image - OBJID ObjectId; //!< Active object id - - IP ObjIpSave; - GP ObjGlobalSave; - LP ObjLocalSave; - DSPSTAT DispatchStatusSave; - ULONG PrioritySave; - - long TimerDataSec; - long TimerDatanSec; - - UWORD Debug; - - UWORD Test; - - UWORD RefCount; - - ULONG TimeuS; - - ULONG OldTime1; - ULONG OldTime2; - ULONG NewTime; -#ifdef ENABLE_PERFORMANCE_TEST - ULONG PerformTimer; - DATAF PerformTime; -#endif - - DSPSTAT DispatchStatus; //!< Dispatch status - ULONG Priority; //!< Object priority - - ULONG Value; - HANDLER Handle; - - ERR Errors[ERROR_BUFFER_SIZE]; - UBYTE ErrorIn; - UBYTE ErrorOut; - - DATA32 MemorySize; - DATA32 MemoryFree; - ULONG MemoryTimer; - -#ifndef DISABLE_SDCARD_SUPPORT - DATA32 SdcardSize; - DATA32 SdcardFree; - ULONG SdcardTimer; - DATA8 SdcardOk; -#endif - -#ifndef DISABLE_USBSTICK_SUPPORT - DATA32 UsbstickSize; - DATA32 UsbstickFree; - ULONG UsbstickTimer; - DATA8 UsbstickOk; -#endif - - LCD LcdBuffer; //!< Copy of last LCD update - DATA8 LcdUpdated; //!< LCD updated - - ANALOG Analog; - ANALOG *pAnalog; - int AdcFile; - -#ifdef ENABLE_STATUS_TEST - DATA8 Status; -#endif - -#ifdef ALLOW_DEBUG_PULSE - DATA8 PulseShow; - DATA8 Pulse; -#endif - -#if (HARDWARE == SIMULATION) - class NXT * nxt; -#endif -}GLOBALS; - - -#if (HARDWARE == SIMULATION) - extern GLOBALS * gInstance; - #define VMInstance (*gInstance) - RESULT mSchedInit(); - RESULT mSchedCtrl(); - RESULT mSchedExit(); - - void setInstance(GLOBALS * _Instance); - GLOBALS * getInstance(); -#else - extern GLOBALS VMInstance; -#endif - - -#endif /* LMS2012_H_ */ diff --git a/brick/kernel/source/lmstypes.h b/brick/kernel/source/lmstypes.h deleted file mode 100644 index 390ed6bd..00000000 --- a/brick/kernel/source/lmstypes.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * As a special exception, if other files instantiate templates or use macros or - * inline functions from this file, or you compile this file and link it with - * other works to produce a work based on this file, this file does not by itself - * cause the resulting work to be covered by the GNU General Public License. - * However the source code for this file must still be made available in accordance - * with section (3) of the GNU General Public License. - * - */ - - -#ifndef LMSTYPES_H_ -#define LMSTYPES_H_ - -// BASIC DATA TYPES - -#ifndef LEGO_SIMULATION - -typedef unsigned char UBYTE; //!< Basic Type used to symbolise 8 bit unsigned values -typedef unsigned short UWORD; //!< Basic Type used to symbolise 16 bit unsigned values -typedef unsigned int ULONG; //!< Basic Type used to symbolise 32 bit unsigned values - -typedef signed char SBYTE; //!< Basic Type used to symbolise 8 bit signed values -typedef signed short SWORD; //!< Basic Type used to symbolise 16 bit signed values -typedef signed int SLONG; //!< Basic Type used to symbolise 32 bit signed values - -typedef float FLOAT; //!< Basic Type used to symbolise 32 bit floating point values - -#define LFILE FILE - -#else - -#include -#include - -typedef LEGO::UInt8 UBYTE; //!< Basic Type used to symbolise 8 bit unsigned values -typedef LEGO::UInt16 UWORD; //!< Basic Type used to symbolise 16 bit unsigned values -typedef unsigned long ULONG; //!< Basic Type used to symbolise 32 bit unsigned values - - -typedef LEGO::Int8 SBYTE; //!< Basic Type used to symbolise 8 bit signed values -typedef LEGO::Int16 SWORD; //!< Basic Type used to symbolise 16 bit signed values -typedef LEGO::Int32 SLONG; //!< Basic Type used to symbolise 32 bit signed values - -typedef LEGO::Real32 FLOAT; //!< Basic Type used to symbolise 32 bit floating point values - -#endif - -// VM DATA TYPES - -typedef SBYTE DATA8; //!< VM Type for 1 byte signed value -typedef SWORD DATA16; //!< VM Type for 2 byte signed value -typedef SLONG DATA32; //!< VM Type for 4 byte signed value -typedef FLOAT DATAF; //!< VM Type for 4 byte floating point value - -// VM VARIABLE TYPES - -typedef UBYTE VARDATA; //!< Variable base type -typedef UBYTE IMGDATA; //!< Image base type - -typedef UWORD PRGID; //!< Program id type - -typedef UWORD OBJID; //!< Object id type -typedef IMGDATA* IP; //!< Instruction pointer type -typedef VARDATA* LP; //!< Local variable pointer type -typedef VARDATA* GP; //!< global variable pointer type - -typedef ULONG IMINDEX; //!< ImageData index type -typedef ULONG GBINDEX; //!< GlobalBytes index type -typedef ULONG LBINDEX; //!< LocalBytes index type -typedef UWORD TRIGGER; //!< TriggerCount type -typedef UBYTE PARS; //!< NoOfParameters type -typedef SLONG IMOFFS; //!< ImageData offset type - -typedef DATA16 HANDLER; //!< Memory list index - - - -/*! \page imagelayout Image Layout - * The image consists of three different components in this fixed order: imageheader, objectheaders and byte codes. - * - * The imageheader tells something about image version, filesize, no of objectheaders (objects) and no of global variable bytes. - * - * - * Objectheaders contains different informations depending on the nature of the object: - * - *- The VMTHREAD object (former TBC_TOPVI) \n - * - OffsetToInstructions tells were to find the corresponding byte codes (offset from image start) \n - * - OwnerObjectId must be zero \n - * - TriggerCount is used but must be zero \n - * - LocalBytes describes the number of bytes for local variables \n - * - *- The SUBCALL object (former TBC_VI and TBC_VI_ALIAS) \n - * - OffsetToInstructions tells were to find the corresponding byte codes (if alias this is equal to mother object) \n - * - OwnerObjectId must be zero \n - * - TriggerCount is used and must be one \n - * - LocalBytes describes the number of bytes for local variables \n - * - *- The BLOCK object (former CLUMP) \n - * - OffsetToInstructions tells were to find the corresponding byte codes (offset from image start) \n - * - OwnerObjectId is equal to object id it belongs to (not equal to zero) \n - * - TriggerCount is used to determine how many triggers needed before the BLOCK object is activated \n - * - LocalBytes must be zero (locals are defined in the owner object) \n - * - * Byte codes are described in a different section. - * - * Little Endian are used (addresses and data are represented with LSB on lowest address and MSB on highest address). - * - * Offset to instructions is number of bytes from start of image to start of object instructions. - * - * Index to global variables are byte based and counted from start of globals (zero based). - * - * Index to local variables are byte based and counted from start of object locals (zero based). - * - * Object ID's is not zero based - First object (VMTHEAD) is named 1. - * - */ - -/*! \page imagelayout - * - * FILE layout (aligned) - * - *- IMGHEAD (aligned) - * - Sign (4 bytes) - * - ImageSize (4 bytes) - * - VersionInfo (2 bytes) - * - NumberOfObjects (2 bytes) - * - GlobalBytes (4 bytes) - */ - -/*! \struct IMGHEAD - * Image header - */ -typedef struct -{ - UBYTE Sign[4]; //!< Place holder for the file type identifier - IMINDEX ImageSize; //!< Image size - UWORD VersionInfo; //!< Version identifier - OBJID NumberOfObjects; //!< Total number of objects in image - GBINDEX GlobalBytes; //!< Number of bytes to allocate for global variables -} -IMGHEAD; - -/*! \page imagelayout - * - *- OBJHEAD (aligned) - * - OffsetToInstructions (4 bytes) - * - OwnerObjectId (2 bytes) - * - TriggerCount (2 bytes) - * - LocalBytes (4 bytes) - * - */ - -/*! \struct OBJHEAD - * Object header used for all types of objects (VMTHREAD, SUBCALL, BLOCK and ALIAS) - */ -typedef struct // Object header -{ - IP OffsetToInstructions; //!< Offset to instructions from image start - OBJID OwnerObjectId; //!< Used by BLOCK's to hold the owner id - TRIGGER TriggerCount; //!< Used to determine how many triggers needed before the BLOCK object is activated - LBINDEX LocalBytes; //!< Number of bytes to allocate for local variables -} -OBJHEAD; - - -/*! \struct LABEL - * Label data hold information used for labels - */ -typedef struct -{ - IMINDEX Addr; //!< Offset to breakpoint address from image start -} -LABEL; - - -#endif /* LMSTYPES_H_ */ diff --git a/brick/kernel/source/validate.h b/brick/kernel/source/validate.h deleted file mode 100644 index 17d118e8..00000000 --- a/brick/kernel/source/validate.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - - -#ifndef VALIDATE_H_ -#define VALIDATE_H_ - -RESULT cValidateInit(void); - -RESULT cValidateExit(void); - -RESULT cValidateDisassemble(IP pI,IMINDEX *pIndex,LABEL *pLabel); - -RESULT cValidateProgram(PRGID PrgId,IP pI,LABEL *pLabel,DATA8 Disassemble); - - -typedef struct -{ - //***************************************************************************** - // Validate Global variables - //***************************************************************************** - - int Row; - IMINDEX ValidateErrorIndex; -} -VALIDATE_GLOBALS; - -#ifndef LEGO_SIMULATION -extern VALIDATE_GLOBALS ValidateInstance; -#else -extern VALIDATE_GLOBALS * gValidateInstance; -#define ValidateInstance (*gValidateInstance) - -void setValidateInstance(VALIDATE_GLOBALS * _Instance); -VALIDATE_GLOBALS * getValidateInstance(); -#endif - - - #endif /* VALIDATE_H_ */ diff --git a/brick/kernel/storage_common.c b/brick/kernel/storage_common.c deleted file mode 100644 index 6b0dde67..00000000 --- a/brick/kernel/storage_common.c +++ /dev/null @@ -1,779 +0,0 @@ -/* - * storage_common.c -- Common definitions for mass storage functionality - * - * Copyright (C) 2003-2008 Alan Stern - * Copyeight (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* - * This file requires the following identifiers used in USB strings to - * be defined (each of type pointer to char): - * - fsg_string_manufacturer -- name of the manufacturer - * - fsg_string_product -- name of the product - * - fsg_string_serial -- product's serial - * - fsg_string_config -- name of the configuration - * - fsg_string_interface -- name of the interface - * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS - * macro is defined prior to including this file. - */ - -/* - * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and - * fsg_hs_intr_in_desc objects as well as - * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES - * macros are not defined. - * - * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER, - * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not - * defined (as well as corresponding entries in string tables are - * missing) and FSG_STRING_INTERFACE has value of zero. - * - * When FSG_NO_OTG is defined fsg_otg_desc won't be defined. - */ - -/* - * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included - * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN - * characters rather then a pointer to void. - */ - - -#include - - -/* Thanks to NetChip Technologies for donating this product ID. - * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. */ -#define FSG_VENDOR_ID 0x0525 /* NetChip */ -#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ - - -/*-------------------------------------------------------------------------*/ - - -#ifndef DEBUG -#undef VERBOSE_DEBUG -#undef DUMP_MSGS -#endif /* !DEBUG */ - -#ifdef VERBOSE_DEBUG -#define VLDBG LDBG -#else -#define VLDBG(lun, fmt, args...) do { } while (0) -#endif /* VERBOSE_DEBUG */ - -#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) -#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) -#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) -#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) - -/* Keep those macros in sync with thos in - * include/linux/ubs/composite.h or else GCC will complain. If they - * are identical (the same names of arguments, white spaces in the - * same places) GCC will allow redefinition otherwise (even if some - * white space is removed or added) warning will be issued. No - * checking if those symbols is defined is performed because warning - * is desired when those macros were defined by someone else to mean - * something else. */ -#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) -#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) -#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) -#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args) -#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args) - - - -#ifdef DUMP_MSGS - -# define dump_msg(fsg, /* const char * */ label, \ - /* const u8 * */ buf, /* unsigned */ length) do { \ - if (length < 512) { \ - DBG(fsg, "%s, length %u:\n", label, length); \ - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ - 16, 1, buf, length, 0); \ - } \ -} while (0) - -# define dump_cdb(fsg) do { } while (0) - -#else - -# define dump_msg(fsg, /* const char * */ label, \ - /* const u8 * */ buf, /* unsigned */ length) do { } while (0) - -# ifdef VERBOSE_DEBUG - -# define dump_cdb(fsg) \ - print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ - 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ - -# else - -# define dump_cdb(fsg) do { } while (0) - -# endif /* VERBOSE_DEBUG */ - -#endif /* DUMP_MSGS */ - - - - - -/*-------------------------------------------------------------------------*/ - -/* SCSI device types */ -#define TYPE_DISK 0x00 -#define TYPE_CDROM 0x05 - -/* USB protocol value = the transport method */ -#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define USB_PR_BULK 0x50 /* Bulk-only */ - -/* USB subclass value = the protocol encapsulation */ -#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */ -#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */ -#define USB_SC_QIC 0x03 /* QIC-157 (tape) */ -#define USB_SC_UFI 0x04 /* UFI (floppy) */ -#define USB_SC_8070 0x05 /* SFF-8070i (removable) */ -#define USB_SC_SCSI 0x06 /* Transparent SCSI */ - -/* Bulk-only data structures */ - -/* Command Block Wrapper */ -struct fsg_bulk_cb_wrap { - __le32 Signature; /* Contains 'USBC' */ - u32 Tag; /* Unique per command id */ - __le32 DataTransferLength; /* Size of the data */ - u8 Flags; /* Direction in bit 7 */ - u8 Lun; /* LUN (normally 0) */ - u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */ - u8 CDB[16]; /* Command Data Block */ -}; - -#define USB_BULK_CB_WRAP_LEN 31 -#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ -#define USB_BULK_IN_FLAG 0x80 - -/* Command Status Wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* Should = 'USBS' */ - u32 Tag; /* Same as original command */ - __le32 Residue; /* Amount not transferred */ - u8 Status; /* See below */ -}; - -#define USB_BULK_CS_WRAP_LEN 13 -#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ -#define USB_STATUS_PASS 0 -#define USB_STATUS_FAIL 1 -#define USB_STATUS_PHASE_ERROR 2 - -/* Bulk-only class specific requests */ -#define USB_BULK_RESET_REQUEST 0xff -#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe - - -/* CBI Interrupt data structure */ -struct interrupt_data { - u8 bType; - u8 bValue; -}; - -#define CBI_INTERRUPT_DATA_LEN 2 - -/* CBI Accept Device-Specific Command request */ -#define USB_CBI_ADSC_REQUEST 0x00 - - -/* Length of a SCSI Command Data Block */ -#define MAX_COMMAND_SIZE 16 - -/* SCSI commands that we recognize */ -#define SC_FORMAT_UNIT 0x04 -#define SC_INQUIRY 0x12 -#define SC_MODE_SELECT_6 0x15 -#define SC_MODE_SELECT_10 0x55 -#define SC_MODE_SENSE_6 0x1a -#define SC_MODE_SENSE_10 0x5a -#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SC_READ_6 0x08 -#define SC_READ_10 0x28 -#define SC_READ_12 0xa8 -#define SC_READ_CAPACITY 0x25 -#define SC_READ_FORMAT_CAPACITIES 0x23 -#define SC_READ_HEADER 0x44 -#define SC_READ_TOC 0x43 -#define SC_RELEASE 0x17 -#define SC_REQUEST_SENSE 0x03 -#define SC_RESERVE 0x16 -#define SC_SEND_DIAGNOSTIC 0x1d -#define SC_START_STOP_UNIT 0x1b -#define SC_SYNCHRONIZE_CACHE 0x35 -#define SC_TEST_UNIT_READY 0x00 -#define SC_VERIFY 0x2f -#define SC_WRITE_6 0x0a -#define SC_WRITE_10 0x2a -#define SC_WRITE_12 0xaa - -/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ -#define SS_NO_SENSE 0 -#define SS_COMMUNICATION_FAILURE 0x040800 -#define SS_INVALID_COMMAND 0x052000 -#define SS_INVALID_FIELD_IN_CDB 0x052400 -#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 -#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 -#define SS_MEDIUM_NOT_PRESENT 0x023a00 -#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 -#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 -#define SS_RESET_OCCURRED 0x062900 -#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 -#define SS_UNRECOVERED_READ_ERROR 0x031100 -#define SS_WRITE_ERROR 0x030c02 -#define SS_WRITE_PROTECTED 0x072700 - -#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ -#define ASC(x) ((u8) ((x) >> 8)) -#define ASCQ(x) ((u8) (x)) - - -/*-------------------------------------------------------------------------*/ - - -struct fsg_lun { - struct file *filp; - loff_t file_length; - loff_t num_sectors; - - unsigned int initially_ro:1; - unsigned int ro:1; - unsigned int removable:1; - unsigned int cdrom:1; - unsigned int prevent_medium_removal:1; - unsigned int registered:1; - unsigned int info_valid:1; - - u32 sense_data; - u32 sense_data_info; - u32 unit_attention_data; - - struct device dev; -}; - -#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL) - -static struct fsg_lun *fsg_lun_from_dev(struct device *dev) -{ - return container_of(dev, struct fsg_lun, dev); -} - - -/* Big enough to hold our biggest descriptor */ -#define EP0_BUFSIZE 256 -#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ - -/* Number of buffers we will use. 2 is enough for double-buffering */ -#define FSG_NUM_BUFFERS 2 - -/* Default size of buffer length. */ -#define FSG_BUFLEN ((u32)16384) - -/* Maximal number of LUNs supported in mass storage function */ -#define FSG_MAX_LUNS 8 - -enum fsg_buffer_state { - BUF_STATE_EMPTY = 0, - BUF_STATE_FULL, - BUF_STATE_BUSY -}; - -struct fsg_buffhd { -#ifdef FSG_BUFFHD_STATIC_BUFFER - char buf[FSG_BUFLEN]; -#else - void *buf; -#endif - enum fsg_buffer_state state; - struct fsg_buffhd *next; - - /* The NetChip 2280 is faster, and handles some protocol faults - * better, if we don't submit any short bulk-out read requests. - * So we will record the intended request length here. */ - unsigned int bulk_out_intended_length; - - struct usb_request *inreq; - int inreq_busy; - struct usb_request *outreq; - int outreq_busy; -}; - -enum fsg_state { - /* This one isn't used anywhere */ - FSG_STATE_COMMAND_PHASE = -10, - FSG_STATE_DATA_PHASE, - FSG_STATE_STATUS_PHASE, - - FSG_STATE_IDLE = 0, - FSG_STATE_ABORT_BULK_OUT, - FSG_STATE_RESET, - FSG_STATE_INTERFACE_CHANGE, - FSG_STATE_CONFIG_CHANGE_DISABLE, - FSG_STATE_CONFIG_CHANGE, - FSG_STATE_DISCONNECT, - FSG_STATE_EXIT, - FSG_STATE_TERMINATED -}; - -enum data_direction { - DATA_DIR_UNKNOWN = 0, - DATA_DIR_FROM_HOST, - DATA_DIR_TO_HOST, - DATA_DIR_NONE -}; - - -/*-------------------------------------------------------------------------*/ - - -static inline u32 get_unaligned_be24(u8 *buf) -{ - return 0xffffff & (u32) get_unaligned_be32(buf - 1); -} - - -/*-------------------------------------------------------------------------*/ - - -enum { -#ifndef FSG_NO_DEVICE_STRINGS - FSG_STRING_MANUFACTURER = 1, - FSG_STRING_PRODUCT, - FSG_STRING_SERIAL, - FSG_STRING_CONFIG, -#endif - FSG_STRING_INTERFACE -}; - - -#ifndef FSG_NO_OTG -static struct usb_otg_descriptor -fsg_otg_desc = { - .bLength = sizeof fsg_otg_desc, - .bDescriptorType = USB_DT_OTG, - - .bmAttributes = USB_OTG_SRP, -}; -#endif - -/* There is only one interface. */ - -static struct usb_interface_descriptor -fsg_intf_desc = { - .bLength = sizeof fsg_intf_desc, - .bDescriptorType = USB_DT_INTERFACE, - - .bNumEndpoints = 2, /* Adjusted during fsg_bind() */ - .bInterfaceClass = USB_CLASS_MASS_STORAGE, - .bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */ - .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ - .iInterface = FSG_STRING_INTERFACE, -}; - -/* Three full-speed endpoint descriptors: bulk-in, bulk-out, - * and interrupt-in. */ - -static struct usb_endpoint_descriptor -fsg_fs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - /* wMaxPacketSize set by autoconfiguration */ -}; - -static struct usb_endpoint_descriptor -fsg_fs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - /* wMaxPacketSize set by autoconfiguration */ -}; - -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_fs_intr_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(2), - .bInterval = 32, /* frames -> 32 ms */ -}; - -#ifndef FSG_NO_OTG -# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2 -#else -# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1 -#endif - -#endif - -static struct usb_descriptor_header *fsg_fs_function[] = { -#ifndef FSG_NO_OTG - (struct usb_descriptor_header *) &fsg_otg_desc, -#endif - (struct usb_descriptor_header *) &fsg_intf_desc, - (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, - (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, -#ifndef FSG_NO_INTR_EP - (struct usb_descriptor_header *) &fsg_fs_intr_in_desc, -#endif - NULL, -}; - - -/* - * USB 2.0 devices need to expose both high speed and full speed - * descriptors, unless they only run at full speed. - * - * That means alternate endpoint descriptors (bigger packets) - * and a "device qualifier" ... plus more construction options - * for the config descriptor. - */ -static struct usb_endpoint_descriptor -fsg_hs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor -fsg_hs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), - .bInterval = 1, /* NAK every 1 uframe */ -}; - -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_hs_intr_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(2), - .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ -}; - -#ifndef FSG_NO_OTG -# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2 -#else -# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1 -#endif - -#endif - -static struct usb_descriptor_header *fsg_hs_function[] = { -#ifndef FSG_NO_OTG - (struct usb_descriptor_header *) &fsg_otg_desc, -#endif - (struct usb_descriptor_header *) &fsg_intf_desc, - (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, - (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, -#ifndef FSG_NO_INTR_EP - (struct usb_descriptor_header *) &fsg_hs_intr_in_desc, -#endif - NULL, -}; - -/* Maxpacket and other transfer characteristics vary by speed. */ -static struct usb_endpoint_descriptor * -fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, - struct usb_endpoint_descriptor *hs) -{ - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) - return hs; - return fs; -} - - -/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ -static struct usb_string fsg_strings[] = { -#ifndef FSG_NO_DEVICE_STRINGS - {FSG_STRING_MANUFACTURER, fsg_string_manufacturer}, - {FSG_STRING_PRODUCT, fsg_string_product}, - {FSG_STRING_SERIAL, fsg_string_serial}, - {FSG_STRING_CONFIG, fsg_string_config}, -#endif - {FSG_STRING_INTERFACE, fsg_string_interface}, - {} -}; - -static struct usb_gadget_strings fsg_stringtab = { - .language = 0x0409, /* en-us */ - .strings = fsg_strings, -}; - - - /*-------------------------------------------------------------------------*/ - -/* If the next two routines are called while the gadget is registered, - * the caller must own fsg->filesem for writing. */ - -static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) -{ - int ro; - struct file *filp = NULL; - int rc = -EINVAL; - struct inode *inode = NULL; - loff_t size; - loff_t num_sectors; - loff_t min_sectors; - - /* R/W if we can, R/O if we must */ - ro = curlun->initially_ro; - if (!ro) { - filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); - if (-EROFS == PTR_ERR(filp)) - ro = 1; - } - if (ro) - filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); - if (IS_ERR(filp)) { - LINFO(curlun, "unable to open backing file: %s\n", filename); - return PTR_ERR(filp); - } - - if (!(filp->f_mode & FMODE_WRITE)) - ro = 1; - - if (filp->f_path.dentry) - inode = filp->f_path.dentry->d_inode; - if (inode && S_ISBLK(inode->i_mode)) { - if (bdev_read_only(inode->i_bdev)) - ro = 1; - } else if (!inode || !S_ISREG(inode->i_mode)) { - LINFO(curlun, "invalid file type: %s\n", filename); - goto out; - } - - /* If we can't read the file, it's no good. - * If we can't write the file, use it read-only. */ - if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { - LINFO(curlun, "file not readable: %s\n", filename); - goto out; - } - if (!(filp->f_op->write || filp->f_op->aio_write)) - ro = 1; - - size = i_size_read(inode->i_mapping->host); - if (size < 0) { - LINFO(curlun, "unable to find file size: %s\n", filename); - rc = (int) size; - goto out; - } - num_sectors = size >> 9; /* File size in 512-byte blocks */ - min_sectors = 1; - if (curlun->cdrom) { - num_sectors &= ~3; /* Reduce to a multiple of 2048 */ - min_sectors = 300*4; /* Smallest track is 300 frames */ - if (num_sectors >= 256*60*75*4) { - num_sectors = (256*60*75 - 1) * 4; - LINFO(curlun, "file too big: %s\n", filename); - LINFO(curlun, "using only first %d blocks\n", - (int) num_sectors); - } - } - if (num_sectors < min_sectors) { - LINFO(curlun, "file too small: %s\n", filename); - rc = -ETOOSMALL; - goto out; - } - - get_file(filp); - curlun->ro = ro; - curlun->filp = filp; - curlun->file_length = size; - curlun->num_sectors = num_sectors; - LDBG(curlun, "open backing file: %s\n", filename); - rc = 0; - -out: - filp_close(filp, current->files); - return rc; -} - - -static void fsg_lun_close(struct fsg_lun *curlun) -{ - if (curlun->filp) { - LDBG(curlun, "close backing file\n"); - fput(curlun->filp); - curlun->filp = NULL; - } -} - - -/*-------------------------------------------------------------------------*/ - -/* Sync the file data, don't bother with the metadata. - * This code was copied from fs/buffer.c:sys_fdatasync(). */ -static int fsg_lun_fsync_sub(struct fsg_lun *curlun) -{ - struct file *filp = curlun->filp; - - if (curlun->ro || !filp) - return 0; - return vfs_fsync(filp, filp->f_path.dentry, 1); -} - -static void store_cdrom_address(u8 *dest, int msf, u32 addr) -{ - if (msf) { - /* Convert to Minutes-Seconds-Frames */ - addr >>= 2; /* Convert to 2048-byte frames */ - addr += 2*75; /* Lead-in occupies 2 seconds */ - dest[3] = addr % 75; /* Frames */ - addr /= 75; - dest[2] = addr % 60; /* Seconds */ - addr /= 60; - dest[1] = addr; /* Minutes */ - dest[0] = 0; /* Reserved */ - } else { - /* Absolute sector */ - put_unaligned_be32(addr, dest); - } -} - - -/*-------------------------------------------------------------------------*/ - - -static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - - return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) - ? curlun->ro - : curlun->initially_ro); -} - -static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); - char *p; - ssize_t rc; - - down_read(filesem); - if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */ - p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1); - if (IS_ERR(p)) - rc = PTR_ERR(p); - else { - rc = strlen(p); - memmove(buf, p, rc); - buf[rc] = '\n'; /* Add a newline */ - buf[++rc] = 0; - } - } else { /* No file, return 0 bytes */ - *buf = 0; - rc = 0; - } - up_read(filesem); - return rc; -} - - -static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - ssize_t rc = count; - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); - int i; - - if (sscanf(buf, "%d", &i) != 1) - return -EINVAL; - - /* Allow the write-enable status to change only while the backing file - * is closed. */ - down_read(filesem); - if (fsg_lun_is_open(curlun)) { - LDBG(curlun, "read-only status change prevented\n"); - rc = -EBUSY; - } else { - curlun->ro = !!i; - curlun->initially_ro = !!i; - LDBG(curlun, "read-only status set to %d\n", curlun->ro); - } - up_read(filesem); - return rc; -} - -static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); - int rc = 0; - - if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { - LDBG(curlun, "eject attempt prevented\n"); - return -EBUSY; /* "Door is locked" */ - } - - /* Remove a trailing newline */ - if (count > 0 && buf[count-1] == '\n') - ((char *) buf)[count-1] = 0; /* Ugh! */ - - /* Eject current medium */ - down_write(filesem); - if (fsg_lun_is_open(curlun)) { - fsg_lun_close(curlun); - curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; - } - - /* Load new medium */ - if (count > 0 && buf[0]) { - rc = fsg_lun_open(curlun, buf); - if (rc == 0) - curlun->unit_attention_data = - SS_NOT_READY_TO_READY_TRANSITION; - } - up_write(filesem); - return (rc < 0 ? rc : count); -} diff --git a/brick/kernel/usb_function.c b/brick/kernel/usb_function.c deleted file mode 100644 index a0ed79a8..00000000 --- a/brick/kernel/usb_function.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * LEGO® MINDSTORMS EV3 - * - * Copyright (C) 2010-2013 The LEGO Group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * This UsbFunction file is based on and inheritated from - * the original file (f_sourcesink.c) and work done by - * David Brownell - * - * >> f_sourcesink.c - USB peripheral source/sink configuration driver << - * - * >> Copyright (C) 2003-2008 David Brownell << - * >> Copyright (C) 2008 by Nokia Corporation << - * - */ - -/* - * - * HID IN/OUT Interrupt transfer FUNCTION ... - * - */ - -struct f_rudolf { - struct usb_function function; - - struct usb_ep *in_ep; - struct usb_ep *out_ep; -}; - -enum // Used for signaling the IN stuff USB-state -{ // Data from the Brick to the HOST - USB_DATA_IDLE, // - USB_DATA_BUSY, // Ongoing USB request - USB_DATA_PENDING, // Data ready for X-fer, but USB busy - USB_DATA_READY, // Initial setting -}; - -int input_state = USB_DATA_IDLE; -struct usb_ep *save_in_ep; -struct usb_request *save_in_req; - -#ifndef PCASM -static inline struct f_rudolf *func_to_rudolf(struct usb_function *f) -{ - return container_of(f, struct f_rudolf, function); -} -#else -// Keep Eclipse happy -#endif - -static struct usb_interface_descriptor rudolf_intf = { - .bLength = sizeof rudolf_intf, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, // Just plain in and out - .bInterfaceClass = USB_CLASS_HID, // We go for NONE custom-driver - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - /* .iInterface = DYNAMIC */ -}; - -static struct hid_descriptor hs_hid_rudolf_desc = { - .bLength = sizeof hs_hid_rudolf_desc, - .bDescriptorType = HID_DT_HID, - .bcdHID = cpu_to_le16(0x0110), - .bCountryCode = 0x00, - .bNumDescriptors = 0x01, // "The one and only" - .desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID - .desc[0].wDescriptorLength = sizeof hs_hid_report_descriptor, - /*.desc[0].bDescriptorType = DYNAMIC */ - /*.desc[0].wDescriptorLenght= DYNAMIC */ -}; - -static struct hid_descriptor fs_hid_rudolf_desc = { - .bLength = sizeof fs_hid_rudolf_desc, - .bDescriptorType = HID_DT_HID, - .bcdHID = cpu_to_le16(0x0110), - .bCountryCode = 0x00, - .bNumDescriptors = 0x01, // "The one and only" - .desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID - .desc[0].wDescriptorLength = sizeof fs_hid_report_descriptor, - -}; - -/* full speed support: */ - -static struct usb_endpoint_descriptor rudolf_out_fs_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 1, /* 1 = 1 mSec POLL rate for FS */ -}; - -static struct usb_endpoint_descriptor rudolf_in_fs_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(64), - .bInterval = 1, /* 1 = 1 mSec POLL rate for FS */ -}; - -/* high speed support: */ - -static struct usb_endpoint_descriptor rudolf_in_hs_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(1024), - .bInterval = 4, /* Calculated as : - * 2^(value-1) * 125uS - * i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec - * - 4: 2^(4-1) * 125 uSec = 1 mSec - */ -}; - -static struct usb_endpoint_descriptor rudolf_out_hs_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(1024), - .bInterval = 4, /* Calculated as : - * 2^(value-1) * 125uS - * i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec - * - 4: 2^(4-1) * 125 uSec = 1 mSec - */ -}; - -static struct usb_descriptor_header *hs_rudolf_descs[] = { - (struct usb_descriptor_header *) &rudolf_intf, - (struct usb_descriptor_header *) &hs_hid_rudolf_desc, - (struct usb_descriptor_header *) &rudolf_in_hs_desc, - (struct usb_descriptor_header *) &rudolf_out_hs_desc, - NULL, -}; - -static struct usb_descriptor_header *fs_rudolf_descs[] = { - (struct usb_descriptor_header *) &rudolf_intf, - (struct usb_descriptor_header *) &fs_hid_rudolf_desc, - (struct usb_descriptor_header *) &rudolf_in_fs_desc, - (struct usb_descriptor_header *) &rudolf_out_fs_desc, - NULL, -}; - -/* function-specific strings: */ - -static struct usb_string strings_rudolf[] = { - [0].s = "Xfer data to and from EV3 brick", - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab_rudolf = { - .language = 0x0409, /* en-us */ - .strings = strings_rudolf, -}; - -static struct usb_gadget_strings *rudolf_strings[] = { - &stringtab_rudolf, - NULL, -}; - -/*-------------------------------------------------------------------------*/ - -static int -f_rudolf_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct usb_composite_dev *cdev = c->cdev; - struct f_rudolf *rudolf = func_to_rudolf(f); - int id; - - /* allocate interface ID(s) */ - id = usb_interface_id(c, f); - if (id < 0) - return id; - rudolf_intf.bInterfaceNumber = id; - - /* allocate endpoints */ - rudolf->in_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_in_fs_desc); - if (!rudolf->in_ep) { -autoconf_fail: - ERROR(cdev, "%s: can't autoconfigure on %s\n", - f->name, cdev->gadget->name); - return -ENODEV; - } - rudolf->in_ep->driver_data = cdev; /* claim */ - - rudolf->out_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_out_fs_desc); - if (!rudolf->out_ep) - goto autoconf_fail; - rudolf->out_ep->driver_data = cdev; /* claim */ - - - /* support high speed hardware */ - if (gadget_is_dualspeed(c->cdev->gadget)) { - - rudolf_in_hs_desc.bEndpointAddress = - rudolf_in_fs_desc.bEndpointAddress; - rudolf_out_hs_desc.bEndpointAddress = - rudolf_out_fs_desc.bEndpointAddress; - f->hs_descriptors = hs_rudolf_descs; - f->descriptors = fs_rudolf_descs; - } - - DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", - gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", - f->name, rudolf->in_ep->name, rudolf->out_ep->name); - return 0; -} - -static void -f_rudolf_unbind(struct usb_configuration *c, struct usb_function *f) -{ - kfree(func_to_rudolf(f)); -} - -static void usb_req_arm(struct usb_ep *ep, struct usb_request *req) -{ - int status; - - if (UsbSpeed.Speed == FULL_SPEED) - { - req->length = 64; - req->actual = 64; - } - else - { - req->length = 1024; - req->actual = 1024; - } - - status = usb_ep_queue(ep, req, GFP_ATOMIC); - if (status) { - usb_ep_set_halt(ep); - /* FIXME recover later ... somehow */ - } -} - -static int read_data_from_host(struct usb_request *req) -{ - unsigned i; - u8 *buf = req->buf; - - int from_host_length = 0; // NO ACCESS LOCKS YET - - // test for actual length > 0 - - for (i = 0; i < req->actual; i++, buf++) - { - - usb_char_buffer_out[i] = *buf; - from_host_length++; - } - - return (from_host_length); -} - -static void write_data_to_the_host(struct usb_ep *ep, struct usb_request *req) -{ - unsigned i; - u8 *buf = req->buf; - - //#define DEBUG - #ifdef DEBUG - printk("WR to HOST req->length = %d\r\n", req->length); - #endif - - #undef DEBUG - //#define DEBUG - #ifdef DEBUG - printk("USB = %d, %d\r\n", usb_char_buffer_in[2], usb_char_buffer_in[3]); - #endif - #undef DEBUG - - for (i = 0; i < req->length; i++) - *buf++ = usb_char_buffer_in[i]; - usb_char_in_length = 0; // Reset and ready -} - -static void rudolf_complete(struct usb_ep *ep, struct usb_request *req) -{ - struct f_rudolf *rudolf = ep->driver_data; - int status = req->status; - - - switch ( status ) { - - case 0: /* normal completion? */ - if (ep == rudolf->out_ep) // An OUT completion? - { - //#define DEBUG - #ifdef DEBUG - printk("Rudolf_complete OUT\n"); - #endif - - usb_char_out_length = read_data_from_host(req); - usb_req_arm(ep, req); - } - else // We have an INPUT request complete - { - //#define DEBUG - #ifdef DEBUG - printk("Rudolf_complete IN\n"); - #endif - - switch(input_state) // State of Brick data x-fer - { - case USB_DATA_READY: //should be BUSY or PENDING.... - - #ifdef DEBUG - printk("IN_IN_IN - READY ?????\n"); - #endif - - break; - - case USB_DATA_PENDING: // - // #define DEBUG - #ifdef DEBUG - printk("IN_IN_IN - PENDING settes to BUSY\n"); - #endif - - input_state = USB_DATA_BUSY; - write_data_to_the_host(ep, req); - usb_req_arm(ep, req); // new request - break; - - case USB_DATA_BUSY: // - #ifdef DEBUG - printk("IN_IN_IN - BUSY settes to READY\n"); - #endif - #undef DEBUG - input_state = USB_DATA_READY; - // and relax - break; - - case USB_DATA_IDLE: // too lazy - #ifdef DEBUG - printk("IN_IN_IN - IDLE\n"); - #endif - //#undef DEBUG - - break; - - default: break; // hmmm. - } - // Reset the buffer size - Ready again - usb_char_in_length = 0; - } - break; - - /* this endpoint is normally active while we're configured */ - - case -ESHUTDOWN: /* disconnect from host */ - // REMOVED 26102012 (*pUsbSpeed).Speed = FULL_SPEED; - case -ECONNABORTED: /* hardware forced ep reset */ - case -ECONNRESET: /* request dequeued */ - //case -ESHUTDOWN: /* disconnect from host */ - if (ep == rudolf->out_ep) - read_data_from_host(req); - free_ep_req(ep, req); - return; - - case -EOVERFLOW: /* buffer overrun on read means that - we didn't provide a big enough - buffer. - */ - default: -//#if 1 - // DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name, - // status, req->actual, req->length); -//#endif - case -EREMOTEIO: /* short read */ - break; - } - -} - -static int rudolf_start_ep(struct f_rudolf *rudolf, bool is_in) -{ - struct usb_ep *ep; - struct usb_request *req; - int status; - - ep = is_in ? rudolf->in_ep : rudolf->out_ep; - req = alloc_ep_req(ep); - if (!req) - return -ENOMEM; - - req->complete = rudolf_complete; - - #ifdef DEBUG - printk("UsbSpeed.Speed = %d\n\r", UsbSpeed.Speed); - #endif - - if (UsbSpeed.Speed == FULL_SPEED) - { - #ifdef DEBUG - printk("rudolf_start_ep FULL\n\r"); - #endif - - (*pUsbSpeed).Speed = FULL_SPEED; - req->length = 64; // Full speed max buffer size - req->actual = 64; - } - else - { - #ifdef DEBUG - printk("rudolf_start_ep HIGH\n\r"); - #endif - - (*pUsbSpeed).Speed = HIGH_SPEED; - req->length = 1024; // High speed max buffer size - req->actual = 1024; - } - - if (is_in) - { - save_in_ep = ep; - save_in_req = req; - - #ifdef DEBUG - printk("req->length = %d ***** Rudolf_Start_Ep_in\n\r", req->length); - #endif - - // reinit_write_data(ep, req); - input_state = USB_DATA_BUSY; - } - else - { - #ifdef DEBUG - printk("***** Rudolf_Start_Ep_out\n"); - #endif - } - - status = usb_ep_queue(ep, req, GFP_ATOMIC); - - if (status) { - struct usb_composite_dev *cdev; - - cdev = rudolf->function.config->cdev; - ERROR(cdev, "start %s %s --> %d\n", - is_in ? "IN" : "OUT", - ep->name, status); - - free_ep_req(ep, req); - } - - return status; -} - -static void disable_rudolf(struct f_rudolf *rudolf) -{ - struct usb_composite_dev *cdev; - - cdev = rudolf->function.config->cdev; - disable_endpoints(cdev, rudolf->in_ep, rudolf->out_ep); - VDBG(cdev, "%s disabled\n", rudolf->function.name); -} - -static int -enable_rudolf(struct usb_composite_dev *cdev, struct f_rudolf *rudolf) -{ - int result = 0; - const struct usb_endpoint_descriptor *ep_in, *ep_out; - struct usb_ep *ep; - - ep_in = ep_choose(cdev->gadget, &rudolf_in_hs_desc, &rudolf_in_fs_desc); - - ep_out = ep_choose(cdev->gadget, &rudolf_out_hs_desc, &rudolf_out_fs_desc); - - ep = rudolf->in_ep; - - result = usb_ep_enable(ep, ep_in); - - if (result < 0) - return result; - - ep->driver_data = rudolf; - - result = rudolf_start_ep(rudolf, true); - - if (result < 0) { -fail: - ep = rudolf->in_ep; - usb_ep_disable(ep); - ep->driver_data = NULL; - return result; - } - - /* one endpoint reads (sinks) anything OUT (from the host) */ - ep = rudolf->out_ep; - result = usb_ep_enable(ep, ep_out); - - if (result < 0) - goto fail; - - ep->driver_data = rudolf; - - result = rudolf_start_ep(rudolf, false); - - if (result < 0) { - usb_ep_disable(ep); - ep->driver_data = NULL; - goto fail; - } - - DBG(cdev, "%s enabled\n", rudolf->function.name); - - return result; -} - -static int f_rudolf_set_alt(struct usb_function *f, - unsigned intf, unsigned alt) -{ - struct f_rudolf *rudolf = func_to_rudolf(f); - struct usb_composite_dev *cdev = f->config->cdev; - - /* we know alt is zero */ - if (rudolf->in_ep->driver_data) - disable_rudolf(rudolf); - - return enable_rudolf(cdev, rudolf); -} - -static void f_rudolf_disable(struct usb_function *f) -{ - struct f_rudolf *rudolf = func_to_rudolf(f); - - disable_rudolf(rudolf); -} - -/*-------------------------------------------------------------------------*/ - -static int msg_config(struct usb_configuration *c); - -static int rudolf_bind_config(struct usb_configuration *c) -{ - struct f_rudolf *rudolf; - int status; - - rudolf = kzalloc(sizeof *rudolf, GFP_KERNEL); - if (!rudolf) - return -ENOMEM; - - rudolf->function.name = "rudolf xfer"; - rudolf->function.descriptors = hs_rudolf_descs; - rudolf->function.bind = f_rudolf_bind; - rudolf->function.unbind = f_rudolf_unbind; - rudolf->function.set_alt = f_rudolf_set_alt; - rudolf->function.disable = f_rudolf_disable; - - status = usb_add_function(c, &rudolf->function); - if (status) { - kfree(rudolf); - return status; - } - - - status = msg_config(c); - if (status) { - kfree(rudolf); - return status; - } - - return status; -} - -#ifndef PCASM -static int rudolf_setup(struct usb_configuration *c, - const struct usb_ctrlrequest *ctrl) -{ - struct usb_request *req = c->cdev->req; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - u16 length = 0; - - /* composite driver infrastructure handles everything except - * the two control test requests. - */ - - switch (ctrl->bRequest) { - - /* - * These are the same vendor-specific requests supported by - * Intel's USB 2.0 compliance test devices. We exceed that - * device spec by allowing multiple-packet requests. - * - * NOTE: the Control-OUT data stays in req->buf ... better - * would be copying it into a scratch buffer, so that other - * requests may safely intervene. - */ - - case 0x5b: /* control WRITE test -- fill the buffer */ - if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) - goto unknown; - if (w_value || w_index) - break; - /* just read that many bytes into the buffer */ - if (w_length > req->length) - break; - value = w_length; - break; - case 0x5c: /* control READ test -- return the buffer */ - if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) - goto unknown; - if (w_value || w_index) - break; - /* expect those bytes are still in the buffer; send back */ - if (w_length > req->length) - break; - value = w_length; - break; - - default: -unknown: - VDBG(c->cdev, - "unknown control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - } - - //HER SKAL HID DESC SENDES!!! - switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { - - - case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8 - | USB_REQ_GET_DESCRIPTOR): - switch (w_value >> 8) { - case HID_DT_REPORT: - //VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n"); - length = w_length; - length = min_t(unsigned short, length, - sizeof hs_hid_report_descriptor); - memcpy(req->buf, hs_hid_report_descriptor, length); - value = length; - goto respond; - break; - - default: - //VDBG(cdev, "Unknown decriptor request 0x%x\n", - // value >> 8); - goto stall; - break; - } - break; - default: - //VDBG(cdev, "Unknown request 0x%x\n", - // ctrl->bRequest); - goto stall; - break; - } - -//HERTIL - /* respond with data transfer or status phase? */ -stall: - return -EOPNOTSUPP; - -respond: - if (value >= 0) { - VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - req->zero = 0; - req->length = value; - value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); - if (value < 0) - ERROR(c->cdev, "source/sinkc response, err %d\n", - value); - } - - /* device either stalls (value < 0) or reports success */ - return value; -} -#else -// Keep Eclipse happy -#endif - -static struct usb_configuration rudolf_driver = { - .label = "rudolf driver", - .strings = rudolf_strings, - .bind = rudolf_bind_config, - .setup = rudolf_setup, - .bConfigurationValue = 1, - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - /* .iConfiguration = DYNAMIC */ -}; - -/** - * - */ - -int rudolf_add(struct usb_composite_dev *cdev, bool autoresume) -{ - int id; - - /* allocate string ID(s) */ - id = usb_string_id(cdev); - if (id < 0) - return id; - strings_rudolf[0].id = id; - - rudolf_intf.iInterface = id; - rudolf_driver.iConfiguration = 1; // id; - - /* support autoresume for remote wakeup testing */ - if (autoresume) - rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - - /* support OTG systems */ - if (gadget_is_otg(cdev->gadget)) { - rudolf_driver.descriptors = otg_desc; - rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - - return usb_add_config(cdev, &rudolf_driver); -} diff --git a/brick/mk b/brick/mk deleted file mode 100755 index e6492cc1..00000000 --- a/brick/mk +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -set -xe -scp -qr kernel uf2daemon Makefile vm:linux/pxt/ -ssh vm "cd linux/pxt; make $1" -mkdir -p bin -scp vm:linux/pxt/bin/* bin/ - diff --git a/brick/scripts/README.md b/brick/scripts/README.md deleted file mode 100644 index d3d6a101..00000000 --- a/brick/scripts/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Patched EV3 image - -The file `ev3-fs.patch` summarizes the changes done to the original V1.09D image. -You can see some text files are edited, the `d_usbdev.ko` is updated (sources in `../kernel`), -`uf2d` added (sources in `../uf2daemon`), and a stock `nbd.ko` module is added. - -Additionally, the `edimax01.ko` is replaced by now much more popular `rtl8192cu.ko` (also stock). - -The init script has a hook for running a shell script from `/mnt/ramdisk/`. This can be used -for testing different modules etc. - -The kernel command line has been modified to: -* disable DMA for the MUSB driver - otherwise the mass storage device is very unstable -* increase the size of dmesg buffer to 128k diff --git a/brick/scripts/dump.js b/brick/scripts/dump.js deleted file mode 100644 index 9e017231..00000000 --- a/brick/scripts/dump.js +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -let fs = require("fs") - -let styles = { - "0": "rxtx", - "1": " tx", - "2": "rx ", -} - -function build() { - let kern = fs.readFileSync( "foo") - let off = 0x0001df30 - - kern = kern.slice(off + 6 * 5, off + 6 * (5 + 6)) -console.log(kern.toString("hex")) -off = 0 - -for (let i = 0; i < 30; ++i) { - if (kern[off+4] == 64) { - kern[off+4] = 0 - kern[off+5] = 2 - } -if(kern[off] == 3 || kern[off] == 4) { - kern[off+4] = 0 - kern[off+5] = 1 -} - console.log(`ep=${kern[off]} style=${styles[kern[off+1]]} buf=${kern[off+2] == 0 ? "sin" : kern[off+2] == 1 ? "dbl" : "XXX"} pad=${kern[off+3]} sz=${kern[off+4]+(kern[off+5]<<8)}`) - off += 6 -} -console.log(kern.toString("hex")) -} - -build() diff --git a/brick/scripts/ev3-fs.patch b/brick/scripts/ev3-fs.patch deleted file mode 100644 index 79e7b259..00000000 --- a/brick/scripts/ev3-fs.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff -ur orig-ev3/etc/init.d/ev3init.sh dev-ev3/etc/init.d/ev3init.sh ---- orig-ev3/etc/init.d/ev3init.sh 1970-01-01 01:00:00.000000000 +0100 -+++ dev-ev3/etc/init.d/ev3init.sh 2017-07-27 12:19:43.195041798 +0100 -@@ -1,5 +1,7 @@ - #!/bin/sh - -+echo Y > /sys/module/printk/parameters/time -+ - bluetoothd -n > /dev/null 2>&1 & - - echo "Setting up VirtualDrive..."; -@@ -60,3 +62,6 @@ - sleep 2 - hciattach /dev/ttyS2 texas 2000000 "flow" "nosleep" $STRING - sdptool add SP -+ -+insmod /lib/modules/2.6.33-rc4/kernel/drivers/net/wireless/rtl8192cu.ko -+. /mnt/ramdisk/rc.local || : -Only in orig-ev3/home/root/lms2012/sys: exit~ -diff -ur orig-ev3/home/root/lms2012/sys/init dev-ev3/home/root/lms2012/sys/init ---- orig-ev3/home/root/lms2012/sys/init 1970-01-01 01:00:00.000000000 +0100 -+++ dev-ev3/home/root/lms2012/sys/init 2017-07-27 12:23:43.072605126 +0100 -@@ -5,13 +5,15 @@ - var=$(printf 'HostStr=%s SerialStr=%s' $(cat /home/root/lms2012/sys/settings/BrickName) $(cat /home/root/lms2012/sys/settings/BTser)) - echo $var > /home/root/lms2012/sys/settings/UsbInfo.dat - -+insmod ${PWD}/mod/nbd.ko -+${PWD}/uf2d - insmod ${PWD}/mod/d_iic.ko `cat /home/root/lms2012/sys/settings/HwId` - insmod ${PWD}/mod/d_uart.ko `cat /home/root/lms2012/sys/settings/HwId` - insmod ${PWD}/mod/d_power.ko `cat /home/root/lms2012/sys/settings/HwId` - insmod ${PWD}/mod/d_pwm.ko `cat /home/root/lms2012/sys/settings/HwId` - insmod ${PWD}/mod/d_ui.ko `cat /home/root/lms2012/sys/settings/HwId` - insmod ${PWD}/mod/d_analog.ko `cat /home/root/lms2012/sys/settings/HwId` --insmod ${PWD}/mod/d_usbdev.ko `cat /home/root/lms2012/sys/settings/UsbInfo.dat` -+insmod ${PWD}/mod/d_usbdev.ko `cat /home/root/lms2012/sys/settings/UsbInfo.dat` file=/dev/nbd0 - insmod ${PWD}/mod/d_usbhost.ko - insmod ${PWD}/mod/d_sound.ko `cat /home/root/lms2012/sys/settings/HwId` - insmod ${PWD}/mod/d_bt.ko `cat /home/root/lms2012/sys/settings/HwId` -@@ -29,6 +31,8 @@ - chmod 666 /dev/lms_iic - chmod 666 /dev/lms_bt - -+echo 4 > /proc/sys/kernel/printk -+ - cd .. - ls -R > /dev/null - cd sys -Binary files orig-ev3/home/root/lms2012/sys/mod/d_usbdev.ko and dev-ev3/home/root/lms2012/sys/mod/d_usbdev.ko differ -Only in dev-ev3/home/root/lms2012/sys/mod: nbd.ko -Only in dev-ev3/home/root/lms2012/sys: uf2d -Only in orig-ev3/lib/modules/2.6.33-rc4/kernel/drivers/net/wireless: edimax01.ko -Only in dev-ev3/lib/modules/2.6.33-rc4/kernel/drivers/net/wireless: rtl8192cu.ko diff --git a/brick/scripts/img.js b/brick/scripts/img.js deleted file mode 100644 index 50036f89..00000000 --- a/brick/scripts/img.js +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh - -let fs = require("fs") -// we try to use shorter versions of all parameters for the additional parameters to fit -let bootargs = "mem=${memsize} initrd=${filesysaddr},${filesyssize} root=/dev/ram0 rw rootfstype=cramfs console=${console} ip=${ipaddr} lpj=747520 quiet" -let bootnews = "mem=64M initrd=0xC1180000,10M root=1:0 rw rootfstype=cramfs console=${console} lpj=747520 musb_hdrc.use_dma=0 log_buf_len=128k quiet" -let piggy = true - -function build() { - if (bootnews.length > bootargs.length) { - console.log("args too long") - return - } - - while (bootnews.length < bootargs.length) - bootnews += " " - - let cr = fs.readFileSync("cram.bin") - - if (cr.length > 10485760) { - console.log("too big by " + (cr.length - 10485760)) - return - } - let img = fs.readFileSync("EV3 Firmware V1.09D.bin") - - for (let i = 0; i < bootnews.length; ++i) { - if (img[0x21DDA + i] != bootargs.charCodeAt(i)) { - console.log("boot args mismatch") - return - } - img[0x21DDA + i] = bootnews.charCodeAt(i) - } - - let off = 0x250000 - if (img[off] != 0x45 || img[off + 1] != 0x3d) { - console.log("bad magic: " + img[off] + " / " + img[off+1]) - return - } - - cr.copy(img, off) - - let kern = fs.readFileSync(piggy ? "piggy-patched.gzip" : "linux/arch/arm/boot/uImage") - off = piggy ? 0x0005540f : 0x00050000 - - if (img[off] != kern[0] || img[off+1] != kern[1]) { - console.log("bad kernel magic: " + img[off] + " / " + img[off+1]) - return - } - - kern.copy(img, off) - - fs.writeFileSync("firmware.bin", img) -} - -build() diff --git a/brick/scripts/mkimg b/brick/scripts/mkimg deleted file mode 100755 index 451712ae..00000000 --- a/brick/scripts/mkimg +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# dd if=EV3\ Firmware\ V1.09D.bin of=orig.cram bs=65536 skip=37 count=400 - -sudo cp linux/pxt/uf2daemon/server dev-ev3/home/root/lms2012/sys/uf2d -sudo cp linux/pxt/kernel/d_usbdev.ko dev-ev3/home/root/lms2012/sys/mod/d_usbdev.ko -sudo chown -R root:root dev-ev3/home/root/lms2012 -sudo mkfs.cramfs dev-ev3 cram.bin -node img -ls -l firmware.bin diff --git a/brick/scripts/patchkern.js b/brick/scripts/patchkern.js deleted file mode 100644 index 8ceb2041..00000000 --- a/brick/scripts/patchkern.js +++ /dev/null @@ -1,8 +0,0 @@ -let small = "010100000004010200000004020100004000020200004000030100000004040000008000" -let big = "010100000004010200000004020100000002020200000002030100000001040000000001" - -let fs = require("fs") - -let kern = fs.readFileSync( "foo") -let kern2 = new Buffer(kern.toString("hex").replace(small, big), "hex") -fs.writeFileSync("foo2", kern2) diff --git a/brick/send b/brick/send deleted file mode 100755 index 631633a3..00000000 --- a/brick/send +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -./mk -ev3duder up bin/d_usbdev.ko ../prjs/ko/d_usbdev.ko -ev3duder up bin/nbd.ko ../prjs/ko/nbd.ko -ev3duder up ins ../prjs/ko/ins -ev3duder exec 'rm ../prjs/ko/uf2d' -ev3duder up bin/uf2d ../prjs/ko/uf2d -#ev3duder exec 'echo . /mnt/ramdisk/prjs/ko/ins > /mnt/ramdisk/rc.local' - diff --git a/brick/uf2daemon/Makefile b/brick/uf2daemon/Makefile deleted file mode 100644 index da877b2e..00000000 --- a/brick/uf2daemon/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -CFLAGS = -std=c99 -W -Wall -SRC = main.c fat.c - -all: - gcc -DX86=1 -g $(CFLAGS) $(SRC) -o server86 - arm-none-linux-gnueabi-gcc -Os -s $(CFLAGS) $(SRC) -o server diff --git a/brick/uf2daemon/fat.c b/brick/uf2daemon/fat.c deleted file mode 100644 index df5fc210..00000000 --- a/brick/uf2daemon/fat.c +++ /dev/null @@ -1,784 +0,0 @@ - -#define VENDOR_NAME "The LEGO Group" -#define PRODUCT_NAME "Mindstorms EV3" -#define VOLUME_LABEL "EV3" -#define INDEX_URL "https://makecode.com/lego" - -#define BOARD_ID "LEGO-EV3-v0" - -#define _XOPEN_SOURCE 500 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define max(a, b) \ - ({ \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a > _b ? _a : _b; \ - }) - -#define min(a, b) \ - ({ \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a < _b ? _a : _b; \ - }) - -#include "uf2.h" - -#define DBG LOG - -typedef struct { - uint8_t JumpInstruction[3]; - uint8_t OEMInfo[8]; - uint16_t SectorSize; - uint8_t SectorsPerCluster; - uint16_t ReservedSectors; - uint8_t FATCopies; - uint16_t RootDirectoryEntries; - uint16_t TotalSectors16; - uint8_t MediaDescriptor; - uint16_t SectorsPerFAT; - uint16_t SectorsPerTrack; - uint16_t Heads; - uint32_t HiddenSectors; - uint32_t TotalSectors32; - uint8_t PhysicalDriveNum; - uint8_t Reserved; - uint8_t ExtendedBootSig; - uint32_t VolumeSerialNumber; - char VolumeLabel[11]; - uint8_t FilesystemIdentifier[8]; -} __attribute__((packed)) FAT_BootBlock; - -typedef struct { - char name[8]; - char ext[3]; - uint8_t attrs; - uint8_t reserved; - uint8_t createTimeFine; - uint16_t createTime; - uint16_t createDate; - uint16_t lastAccessDate; - uint16_t highStartCluster; - uint16_t updateTime; - uint16_t updateDate; - uint16_t startCluster; - uint32_t size; -} __attribute__((packed)) DirEntry; - -typedef struct { - uint8_t seqno; - uint16_t name0[5]; - uint8_t attrs; - uint8_t type; - uint8_t checksum; - uint16_t name1[6]; - uint16_t startCluster; - uint16_t name2[2]; -} __attribute__((packed)) VFatEntry; - -STATIC_ASSERT(sizeof(DirEntry) == 32); - -#define STR0(x) #x -#define STR(x) STR0(x) -const char infoUf2File[] = // - "UF2 Bootloader " UF2_VERSION "\r\n" - "Model: " PRODUCT_NAME "\r\n" - "Board-ID: " BOARD_ID "\r\n"; - -const char indexFile[] = // - "\n" - "" - "" - "" - "" - "\n"; - -#define RESERVED_SECTORS 1 -#define ROOT_DIR_SECTORS 4 -#define SECTORS_PER_FAT ((NUM_FAT_BLOCKS * 2 + 511) / 512) - -#define START_FAT0 RESERVED_SECTORS -#define START_FAT1 (START_FAT0 + SECTORS_PER_FAT) -#define START_ROOTDIR (START_FAT1 + SECTORS_PER_FAT) -#define START_CLUSTERS (START_ROOTDIR + ROOT_DIR_SECTORS) -#define ROOT_DIR_ENTRIES (ROOT_DIR_SECTORS * 512 / 32) - -#define F_TEXT 1 -#define F_UF2 2 -#define F_DIR 4 -#define F_CONT 8 - -static const FAT_BootBlock BootBlock = { - .JumpInstruction = {0xeb, 0x3c, 0x90}, - .OEMInfo = "UF2 UF2 ", - .SectorSize = 512, - .SectorsPerCluster = 1, - .ReservedSectors = RESERVED_SECTORS, - .FATCopies = 2, - .RootDirectoryEntries = ROOT_DIR_ENTRIES, - .TotalSectors16 = NUM_FAT_BLOCKS - 2, - .MediaDescriptor = 0xF8, - .SectorsPerFAT = SECTORS_PER_FAT, - .SectorsPerTrack = 1, - .Heads = 1, - .ExtendedBootSig = 0x29, - .VolumeSerialNumber = 0x00420042, - .VolumeLabel = VOLUME_LABEL, - .FilesystemIdentifier = "FAT16 ", -}; - -int currCluster = 2; -struct FsEntry *rootDir; -struct ClusterData *firstCluster, *lastCluster; - -typedef struct ClusterData { - int flags; - int numclusters; - struct stat st; - struct ClusterData *dnext; - struct ClusterData *cnext; - struct FsEntry *dirdata; - struct FsEntry *myfile; - char name[0]; -} ClusterData; - -typedef struct FsEntry { - int startCluster; - uint8_t attrs; - int size; - int numdirentries; - time_t ctime, mtime; - struct FsEntry *next; - struct ClusterData *data; - char fatname[12]; - char vfatname[0]; -} FsEntry; - -struct DirMap { - const char *mapName; - const char *fsName; -}; - -struct DirMap dirMaps[] = { // -#ifdef X86 - {"foo qux baz", "dirs/bar"}, // - {"foo", "dirs/foo"}, // - {"xyz", "dirs/bar2"}, // -#else - {"Projects", "/mnt/ramdisk/prjs/BrkProg_SAVE"}, - {"SD Card", "/media/card/myapps"}, - {"USB Stick", "/media/usb/myapps"}, -#endif - {NULL, NULL}}; - -void timeToFat(time_t t, uint16_t *dateP, uint16_t *timeP) { - struct tm tm; - - localtime_r(&t, &tm); - - if (timeP) - *timeP = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec / 2); - - if (dateP) - *dateP = (max(0, tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday; -} - -void padded_memcpy(char *dst, const char *src, int len) { - for (int i = 0; i < len; ++i) { - if (*src) - *dst = *src++; - else - *dst = ' '; - dst++; - } -} - -char *expandMap(const char *mapName) { - static char mapbuf[300]; - - const char *rest = ""; - for (int i = 0; i < (int)sizeof(mapbuf); ++i) { - char c = mapName[i]; - if (c == '/' || c == 0) { - mapbuf[i] = 0; - rest = mapName + i; - break; - } - mapbuf[i] = c; - } - for (int i = 0; dirMaps[i].mapName; ++i) { - if (strcmp(dirMaps[i].mapName, mapbuf) == 0) { - strcpy(mapbuf, dirMaps[i].fsName); - strcat(mapbuf, rest); - return mapbuf; - } - } - return NULL; -} - -ClusterData *mkClusterData(int namelen) { - ClusterData *c = malloc(sizeof(*c) + namelen + 1); - memset(c, 0, sizeof(*c) + namelen + 1); - return c; -} - -ClusterData *readDir(const char *mapName) { - DIR *d = opendir(expandMap(mapName)); - if (!d) - return NULL; - - ClusterData *res = NULL; - for (;;) { - struct dirent *ent = readdir(d); - if (!ent) - break; - - ClusterData *c = mkClusterData(strlen(mapName) + 1 + strlen(ent->d_name)); - - c->flags = F_UF2; - c->dnext = res; - sprintf(c->name, "%s/%s", mapName, ent->d_name); - - int err = stat(expandMap(c->name), &c->st); - assert(err >= 0); - - if (S_ISREG(c->st.st_mode) && strlen(c->name) < UF2_FILENAME_MAX) { - c->numclusters = (c->st.st_size + 255) / 256; - } else { - free(c); - continue; - } - - res = c; - } - - closedir(d); - return res; -} - -int filechar(int c) { - if (!c) - return 0; - return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || - strchr("_-", c); -} - -void copyFsChars(char *dst, const char *src, int len) { - for (int i = 0; i < len; ++i) { - if (filechar(*src)) - dst[i] = toupper(*src++); - else { - if (*src == '.') - src = ""; - if (*src == 0) - dst[i] = ' '; - else - dst[i] = '_'; - while (*src && !filechar(*src)) - src++; - } - } -} - -FsEntry *mkFsEntry(const char *name) { - int sz = sizeof(FsEntry) + strlen(name) + 1; - FsEntry *e = malloc(sz); - memset(e, 0, sz); - e->startCluster = currCluster; - e->next = NULL; - // +1 for final 0x0000, and +12 for alignment - e->numdirentries = 1 + (strlen(name) + 1 + 12) / 13; - strcpy(e->vfatname, name); - - const char *src = name; - copyFsChars(e->fatname, src, 8); - while (*src && *src != '.') - src++; - if (*src == '.') - src++; - else - src = ""; - copyFsChars(e->fatname + 8, src, 3); - return e; -} - -void addClusterData(ClusterData *c, FsEntry *e) { - currCluster += c->numclusters; - - if (firstCluster == NULL) { - firstCluster = c; - } else { - lastCluster->cnext = c; - } - lastCluster = c; - - if (c->st.st_ctime) - e->ctime = min(e->ctime, c->st.st_ctime); - e->mtime = max(e->mtime, c->st.st_mtime); - - c->myfile = e; - - DBG("add cluster: flags=%d size=%d numcl=%d", c->flags, (int)c->st.st_size, c->numclusters); -} - -FsEntry *addRootText(const char *filename, const char *contents) { - FsEntry *e = mkFsEntry(filename); - e->next = rootDir; - rootDir = e; - - int sz = strlen(contents); - e->size = sz; - if (sz > 0) { - assert(sz <= 512); - ClusterData *c = mkClusterData(sz); - c->st.st_mtime = c->st.st_ctime = time(NULL); - - c->flags = F_TEXT; - strcpy(c->name, contents); - c->st.st_size = sz; - c->numclusters = 1; - addClusterData(c, e); - } - return e; -} - -int baseLen(const char *a) { - int len = 0; - while (*a && *a != '.') { - a++; - len++; - } - return len; -} - -int nameMatches(const char *a, const char *b) { - for (;;) { - if ((*a == 0 || *a == '.') && (*b == 0 || *b == '.')) - return 1; - - if (*a != *b) - return 0; - a++; - b++; - } -} - -void setFatNames(FsEntry *dirent) { - for (FsEntry *p = dirent; p; p = p->next) { - // check for collisions - int k = 1; - retry: - for (FsEntry *o = dirent; o && o != p; o = o->next) { - if (strcmp(o->fatname, p->fatname) == 0) { - char buf[20]; - sprintf(buf, "~%d", k++); - int len = strlen(buf); - memcpy(p->fatname + 8 - len, buf, len); - goto retry; - } - } - - DBG("setname: %s [%s] cl=%s @ %d sz=%d dents=%d", p->vfatname, p->fatname, - p->data ? p->data->name : "(no data)", p->startCluster, p->size, p->numdirentries); - } -} - -void addFullDir(const char *mapName) { - int numEntries = 0; - FsEntry *dirents = NULL; - - time_t mtime = 0, ctime = 0; - - for (ClusterData *cl = readDir(mapName); cl; cl = cl->dnext) { - if (cl->cnext || cl == lastCluster) - continue; // already done - - // vfat entries - const char *filename = strchr(cl->name, '/') + 1; - int len = baseLen(filename) + 4; - char namebuf[len]; - memcpy(namebuf, filename, len - 4); - strcpy(namebuf + len - 4, ".uf2"); - - assert(cl->flags & F_UF2); - - FsEntry *fent = mkFsEntry(namebuf); - numEntries += fent->numdirentries; - fent->next = dirents; - fent->data = cl; - fent->size = cl->numclusters * 512; - dirents = fent; - addClusterData(cl, fent); - for (ClusterData *other = cl->dnext; other; other = other->dnext) { - if (nameMatches(cl->name, other->name)) { - other->flags |= F_CONT; - fent->size += other->numclusters * 512; - addClusterData(other, fent); - } - } - if (mtime == 0) { - mtime = fent->mtime; - ctime = fent->ctime; - } else { - mtime = max(mtime, fent->mtime); - ctime = min(ctime, fent->ctime); - } - } - - setFatNames(dirents); - - FsEntry *dent = mkFsEntry(mapName); - dent->data = mkClusterData(0); - dent->data->dirdata = dirents; - dent->data->numclusters = (numEntries + 16) / 16; // at least 1 - addClusterData(dent->data, dent); - dent->mtime = mtime; - dent->ctime = ctime; - dent->next = rootDir; - dent->attrs = 0x10; - dent->data->flags = F_DIR; - rootDir = dent; -} - -void setupFs() { - addRootText("info_uf2.txt", infoUf2File); - addRootText("index.html", indexFile); - for (int i = 0; dirMaps[i].mapName; ++i) { - addFullDir(dirMaps[i].mapName); - } - - setFatNames(rootDir); // make names unique - - FsEntry *e = addRootText(BootBlock.VolumeLabel, ""); - e->numdirentries = 1; - e->attrs = 0x28; -} - -#define WRITE_ENT(v) \ - do { \ - if (skip++ >= 0) \ - *dest++ = v; \ - if (skip >= 256) \ - return; \ - cl++; \ - } while (0) - -void readFat(uint16_t *dest, int skip) { - int cl = 0; - skip = -skip; - WRITE_ENT(0xfff0); - WRITE_ENT(0xffff); - for (ClusterData *c = firstCluster; c; c = c->cnext) { - for (int i = 0; i < c->numclusters - 1; i++) - WRITE_ENT(cl + 1); - if (c->cnext && c->cnext->flags & F_CONT) - WRITE_ENT(cl + 1); - else - WRITE_ENT(0xffff); - } -} - -// note that ptr might be unaligned -const char *copyVFatName(const char *ptr, void *dest, int len) { - uint8_t *dst = dest; - - for (int i = 0; i < len; ++i) { - if (ptr == NULL) { - *dst++ = 0xff; - *dst++ = 0xff; - } else { - *dst++ = *ptr; - *dst++ = 0; - if (*ptr) - ptr++; - else - ptr = NULL; - } - } - - return ptr; -} - -uint8_t fatChecksum(const char *name) { - uint8_t sum = 0; - for (int i = 0; i < 11; ++i) - sum = ((sum & 1) << 7) + (sum >> 1) + *name++; - return sum; -} - -void readDirData(uint8_t *dest, FsEntry *dirdata, int blkno) { - DirEntry *d = (void *)dest; - int idx = blkno * -16; - for (FsEntry *e = dirdata; e; e = e->next) { - if (idx >= 16) - break; - - // DBG("dir idx=%d %s", idx, e->vfatname); - - for (int i = 0; i < e->numdirentries; ++i, ++idx) { - if (0 <= idx && idx < 16) { - if (i == e->numdirentries - 1) { - memcpy(d->name, e->fatname, 11); - d->attrs = e->attrs; - d->size = e->size; - d->startCluster = e->startCluster; - timeToFat(e->mtime, &d->updateDate, &d->updateTime); - timeToFat(e->ctime, &d->createDate, &d->createTime); - } else { - VFatEntry *f = (void *)d; - int seq = e->numdirentries - i - 2; - f->seqno = seq + 1; // they start at 1 - if (i == 0) - f->seqno |= 0x40; - f->attrs = 0x0F; - f->type = 0x00; - f->checksum = fatChecksum(e->fatname); - f->startCluster = 0; - - const char *ptr = e->vfatname + (13 * seq); - ptr = copyVFatName(ptr, f->name0, 5); - ptr = copyVFatName(ptr, f->name1, 6); - ptr = copyVFatName(ptr, f->name2, 2); - } - d++; - } - } - } -} - -void readBlock(uint8_t *dest, int blkno) { - // DBG("readbl %d", blkno); - int blkno0 = blkno; - for (ClusterData *c = firstCluster; c; c = c->cnext) { - // DBG("off=%d sz=%d", blkno, c->numclusters); - if (blkno >= c->numclusters) { - blkno -= c->numclusters; - continue; - } - // DBG("readbl off=%d %p", blkno, c); - if (c->dirdata) { - readDirData(dest, c->dirdata, blkno); - } else if (c->flags & F_TEXT) { - strcpy((char *)dest, c->name); - } else if (c->flags & F_UF2) { - UF2_Block *bl = (void *)dest; - - bl->magicStart0 = UF2_MAGIC_START0; - bl->magicStart1 = UF2_MAGIC_START1; - bl->magicEnd = UF2_MAGIC_END; - bl->flags = UF2_FLAG_FILE; - bl->blockNo = blkno0 - (c->myfile->startCluster - 2); - bl->numBlocks = c->myfile->size / 512; - bl->targetAddr = blkno * 256; - bl->payloadSize = 256; - bl->fileSize = c->st.st_size; - - int fd = open(expandMap(c->name), O_RDONLY); - if (fd >= 0) { - lseek(fd, bl->targetAddr, SEEK_SET); - bl->payloadSize = read(fd, bl->data, 256); - close(fd); - } else { - bl->payloadSize = -1; - } - - if (bl->payloadSize < 475 - strlen(c->name)) - strcpy((char *)bl->data + bl->payloadSize, c->name); - } - return; - } -} - -void read_block(uint32_t block_no, uint8_t *data) { - memset(data, 0, 512); - uint32_t sectionIdx = block_no; - - if (block_no == 0) { - memcpy(data, &BootBlock, sizeof(BootBlock)); - data[510] = 0x55; - data[511] = 0xaa; - // logval("data[0]", data[0]); - } else if (block_no < START_ROOTDIR) { - sectionIdx -= START_FAT0; - if (sectionIdx >= SECTORS_PER_FAT) // second copy of fat? - sectionIdx -= SECTORS_PER_FAT; - - readFat((void *)data, sectionIdx * 256); - } else if (block_no < START_CLUSTERS) { - sectionIdx -= START_ROOTDIR; - readDirData(data, rootDir, sectionIdx); - } else { - sectionIdx -= START_CLUSTERS; - readBlock(data, sectionIdx); - } -} - -char rbfPath[300]; - -uint8_t stopApp[] = { - 0x05, 0x00, // size - 0x00, 0x00, // seq. no. - 0x3f, 0x3d, // usb magic, - 0x02, // req. no. -}; - -uint8_t runStart[] = {0x00, 0x00, // size - 0x00, 0x00, // seq. no. - 0x00, 0x00, 0x08, // something - 0xC0, 0x08, 0x82, 0x01, 0x00, 0x84}; - -uint8_t runEnd[] = {0x00, 0x60, 0x64, 0x03, 0x01, 0x60, 0x64, 0x00}; - -#define FEED_DATA _IOC(_IOC_WRITE, 't', 108, 1024) - -void startRbf() { - char buf[1024]; - memset(buf, 0, sizeof(buf)); - memcpy(buf, stopApp, sizeof(stopApp)); - - int fd = open("/dev/lms_usbdev", O_RDWR); - ioctl(fd, FEED_DATA, buf); - usleep(500000); - - int off = 0; - memcpy(buf + off, runStart, sizeof(runStart)); - off += sizeof(runStart); - strcpy(buf + off, rbfPath); - off += strlen(rbfPath); - memcpy(buf + off, runEnd, sizeof(runEnd)); - off += sizeof(runEnd); - off -= 2; - buf[0] = off & 0xff; - buf[1] = off >> 8; - ioctl(fd, FEED_DATA, buf); - - close(fd); -} - -#define MAX_BLOCKS 8000 -typedef struct { - uint32_t numBlocks; - uint32_t numWritten; - uint8_t writtenMask[MAX_BLOCKS / 8 + 1]; -} WriteState; - -void restartProgram() { - if (!rbfPath[0]) - exit(0); - startRbf(); - exit(0); // causes parent to eject MSD etc -} - -int numWrites = 0; -static WriteState wrState; -void write_block(uint32_t block_no, uint8_t *data) { - WriteState *state = &wrState; - - UF2_Block *bl = (void *)data; - - if (bl->magicStart0 == 0x20da6d81 && bl->magicStart1 == 0x747e09d4) { - DBG("restart req, #wr=%d", numWrites); - if (numWrites) { - exit(0); - } - return; - } - - numWrites++; - - if (!is_uf2_block(bl)) { - return; - } - - (void)block_no; - - bl->data[475] = 0; // make sure we have NUL terminator - char *fn0 = (char *)bl->data + bl->payloadSize; - int namelen = 0; - if (bl->payloadSize <= UF2_MAX_PAYLOAD) { - namelen = strlen(fn0); - } - - if ((bl->flags & UF2_FLAG_FILE) && bl->fileSize <= UF2_MAX_FILESIZE && - bl->targetAddr < bl->fileSize && 1 <= namelen && namelen <= UF2_FILENAME_MAX) { - - char *firstSL = strchr(fn0, '/'); - char *lastSL = strrchr(fn0, '/'); - if (!lastSL) - lastSL = fn0; - else - lastSL++; - int baseLen = strlen(lastSL); - char fallback[strlen(dirMaps[0].fsName) + 1 + baseLen + 1]; - sprintf(fallback, "%s/%s", dirMaps[0].fsName, lastSL); - char *fn = NULL; - - if (firstSL && firstSL + 1 == lastSL) - fn = expandMap(fn0); - if (!fn) - fn = fallback; - - char *p = strrchr(fn, '/'); - *p = 0; - mkdir(fn, 0777); - *p = '/'; - - int fd = open(fn, O_WRONLY | O_CREAT, 0777); - if (fd < 0 && errno == ETXTBSY) { - unlink(fn); - fd = open(fn, O_WRONLY | O_CREAT, 0777); - } - if (fd >= 0) { - ftruncate(fd, bl->fileSize); - lseek(fd, bl->targetAddr, SEEK_SET); - // DBG("write %d bytes at %d to %s", bl->payloadSize, bl->targetAddr, fn); - write(fd, bl->data, bl->payloadSize); - close(fd); - - if (strlen(fn) > 4 && !strcmp(fn + strlen(fn) - 4, ".rbf")) { - strcpy(rbfPath, fn); - } - } - } - - if (state && bl->numBlocks) { - if (state->numBlocks != bl->numBlocks) { - if (bl->numBlocks >= MAX_BLOCKS || state->numBlocks) - state->numBlocks = 0xffffffff; - else - state->numBlocks = bl->numBlocks; - } - if (bl->blockNo < MAX_BLOCKS) { - uint8_t mask = 1 << (bl->blockNo % 8); - uint32_t pos = bl->blockNo / 8; - if (!(state->writtenMask[pos] & mask)) { - // logval("incr", state->numWritten); - state->writtenMask[pos] |= mask; - state->numWritten++; - DBG("write %d/%d #%d", state->numWritten, state->numBlocks, bl->blockNo); - } - if (state->numWritten >= state->numBlocks) { - restartProgram(); - } - } - } else { - // TODO timeout for restart? - } -} diff --git a/brick/uf2daemon/main.c b/brick/uf2daemon/main.c deleted file mode 100644 index 1fed6356..00000000 --- a/brick/uf2daemon/main.c +++ /dev/null @@ -1,231 +0,0 @@ -#define _GNU_SOURCE 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uf2.h" - -const char *dev_file = "/dev/nbd0"; - - -#define NUM_BLOCKS NUM_FAT_BLOCKS - -uint64_t ntohll(uint64_t a) { - return ((uint64_t)ntohl(a & 0xffffffff) << 32) | ntohl(a >> 32); -} -#define htonll ntohll - -void mylog(const char *fmt, ...) { - va_list args; - char *p, *p2; - - va_start(args, fmt); - vasprintf(&p, fmt, args); - vprintf(fmt, args); - va_end(args); - - if (p[0] != '<') - asprintf(&p2, "<6>%s\n", p); - else - asprintf(&p2, "%s\n", p); - - int len = strlen(p2); - -#ifdef X86 - write(2, p2, len); -#else - int fd = open("/dev/kmsg", O_WRONLY); - write(fd, p2, len); - close(fd); -#endif - - free(p); - free(p2); -} - -void readAll(int fd, void *dst, uint32_t length) { - while (length) { - int curr = read(fd, dst, length); - if (curr < 0) - FAIL("read failed on fd:%d", fd); - length -= curr; - dst = (char *)dst + curr; - } -} - -void writeAll(int fd, void *dst, uint32_t length) { - while (length) { - int curr = write(fd, dst, length); - if (curr < 0) - FAIL("write failed on fd:%d", fd); - length -= curr; - dst = (char *)dst + curr; - } -} - -int nbd; -int sock; -int sockets[2]; -struct nbd_request request; -struct nbd_reply reply; - -void nbd_ioctl(unsigned id, int arg) { - int err = ioctl(nbd, id, arg); - if (err < 0) - FAIL("ioctl(%ud) failed [%s]", id, strerror(errno)); -} - -void startclient() { - close(sockets[0]); - nbd_ioctl(NBD_SET_SOCK, sockets[1]); - nbd_ioctl(NBD_DO_IT, 0); - nbd_ioctl(NBD_CLEAR_QUE, 0); - nbd_ioctl(NBD_CLEAR_SOCK, 0); - exit(0); -} - -void handleread(int off, int len) { - uint8_t buf[512]; - LOG("read @%d len=%d", off, len); - reply.error = 0; // htonl(EPERM); - writeAll(sock, &reply, sizeof(struct nbd_reply)); - for (int i = 0; i < len; ++i) { - read_block(off + i, buf); - writeAll(sock, buf, 512); - } -} - -void handlewrite(int off, int len) { - uint8_t buf[512]; - LOG("write @%d len=%d", off, len); - for (int i = 0; i < len; ++i) { - readAll(sock, buf, 512); - write_block(off + i, buf); - } - reply.error = 0; - writeAll(sock, &reply, sizeof(struct nbd_reply)); -} - -void setupFs(); - -void runNBD() { - setupFs(); - - int err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); - assert(err >= 0); - - nbd = open(dev_file, O_RDWR); - assert(nbd >= 0); - - nbd_ioctl(BLKFLSBUF, 0); - nbd_ioctl(NBD_SET_BLKSIZE, 512); - nbd_ioctl(NBD_SET_SIZE_BLOCKS, NUM_BLOCKS); - nbd_ioctl(NBD_CLEAR_SOCK, 0); - - if (!fork()) - startclient(); - - int fd = open(dev_file, O_RDONLY); - assert(fd != -1); - close(fd); - - close(sockets[1]); - sock = sockets[0]; - - reply.magic = htonl(NBD_REPLY_MAGIC); - reply.error = htonl(0); - - for (;;) { - // nbd_ioctl(BLKFLSBUF, 0); // flush buffers - we don't want the kernel to cache the writes - int nread = read(sock, &request, sizeof(request)); - - if (nread < 0) { - FAIL("nbd read err %s", strerror(errno)); - } - if (nread == 0) - return; - assert(nread == sizeof(request)); - memcpy(reply.handle, request.handle, sizeof(reply.handle)); - reply.error = htonl(0); - - assert(request.magic == htonl(NBD_REQUEST_MAGIC)); - - uint32_t len = ntohl(request.len); - assert((len & 511) == 0); - len >>= 9; - uint64_t from = ntohll(request.from); - assert((from & 511) == 0); - from >>= 9; - - switch (ntohl(request.type)) { - case NBD_CMD_READ: - handleread(from, len); - break; - case NBD_CMD_WRITE: - handlewrite(from, len); - break; - case NBD_CMD_DISC: - return; - default: - FAIL("invalid cmd: %d", ntohl(request.type)); - } - } -} - -void enableMSD(int enabled) { -#ifndef X86 - int fd = open("/sys/devices/platform/musb_hdrc/gadget/lun0/active", O_WRONLY); - write(fd, enabled ? "1" : "0", 1); - close(fd); -#else - LOG("fake enable MSD: %d", enabled); -#endif -} - -int main(int argc, char **argv) { -#ifndef X86 - daemon(0, 1); -#endif - - if (argc > 1) - dev_file = argv[1]; - - for (;;) { - pid_t child = fork(); - if (child == 0) { - runNBD(); - return 0; - } - - sleep(1); - enableMSD(1); - - int wstatus = 0; - waitpid(child, &wstatus, 0); - enableMSD(0); // force "eject" - - if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { - LOG("abnormal child return, %d", child); - sleep(5); - } else { - sleep(2); - } - } - - return 0; -} \ No newline at end of file diff --git a/brick/uf2daemon/uf2.h b/brick/uf2daemon/uf2.h deleted file mode 100644 index 60560ab3..00000000 --- a/brick/uf2daemon/uf2.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef UF2_H -#define UF2_H 1 - -#include "uf2format.h" -#include -#include - -#ifndef INDEX_URL -#define INDEX_URL "https://www.pxt.io/" -#endif - -#define UF2_VERSION_BASE "v0.1.0" - -// needs to be more than ~4200 and less than ~65000 (to force FAT16) -#define NUM_FAT_BLOCKS 65000 - -#define UF2_VERSION UF2_VERSION_BASE " F" - -//! Static block size for all memories -#define UDI_MSC_BLOCK_SIZE 512L - -void read_block(uint32_t block_no, uint8_t *data); - -void write_block(uint32_t block_no, uint8_t *data); - -#define CONCAT_1(a, b) a##b -#define CONCAT_0(a, b) CONCAT_1(a, b) -#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) } - -extern const char infoUf2File[]; - -void readAll(int fd, void *dst, uint32_t length); - -STATIC_ASSERT(sizeof(UF2_Block) == 512); - -void mylog(const char *fmt, ...); - -#define FAIL(args...) \ - do { \ - mylog("<4>" args); \ - exit(1); \ - } while (0) - -#define LOG mylog - -#endif diff --git a/brick/uf2daemon/uf2format.h b/brick/uf2daemon/uf2format.h deleted file mode 100644 index b69d3780..00000000 --- a/brick/uf2daemon/uf2format.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef UF2FORMAT_H -#define UF2FORMAT_H 1 - -#include -#include - -// All entries are little endian. - -// if you increase that, you will also need to update the linker script file -#define APP_START_ADDRESS 0x00002000 - -#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n" -#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected -#define UF2_MAGIC_END 0x0AB16F30UL // Ditto - -// If set, the block is "comment" and should not be flashed to the device -#define UF2_FLAG_NOFLASH 0x00000001 -#define UF2_FLAG_FILE 0x00001000 -#define UF2_FILENAME_MAX 150 -#define UF2_MAX_PAYLOAD (476 - 10) // leaving some space for filename -// for this bootloader -#define UF2_MAX_FILESIZE (64 * 1024 * 1024) - -typedef struct { - // 32 byte header - uint32_t magicStart0; - uint32_t magicStart1; - uint32_t flags; - uint32_t targetAddr; - uint32_t payloadSize; - uint32_t blockNo; - uint32_t numBlocks; - uint32_t fileSize; - - // raw data, followed by filename (NUL-terminated) at payloadSize - uint8_t data[476]; - - // store magic also at the end to limit damage from partial block reads - uint32_t magicEnd; -} UF2_Block; - -static inline bool is_uf2_block(void *data) { - UF2_Block *bl = (UF2_Block *)data; - return bl->magicStart0 == UF2_MAGIC_START0 && bl->magicStart1 == UF2_MAGIC_START1 && - bl->magicEnd == UF2_MAGIC_END; -} - -#endif diff --git a/brick/uf2daemon/uf2hid.h b/brick/uf2daemon/uf2hid.h deleted file mode 100644 index 78554e63..00000000 --- a/brick/uf2daemon/uf2hid.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef UF2_HID_H -#define UF2_HID_H 1 - -#define HF2_CMD_BININFO 0x0001 -// no arguments -#define HF2_MODE_BOOTLOADER 0x01 -#define HF2_MODE_USERSPACE 0x02 -struct HF2_BININFO_Result { - uint32_t mode; - uint32_t flash_page_size; - uint32_t flash_num_pages; - uint32_t max_message_size; -}; - -#define HF2_CMD_INFO 0x0002 -// no arguments -// results is utf8 character array - -#define HF2_CMD_RESET_INTO_APP 0x0003 -// no arguments, no result - -#define HF2_CMD_RESET_INTO_BOOTLOADER 0x0004 -// no arguments, no result - -#define HF2_CMD_START_FLASH 0x0005 -// no arguments, no result - -#define HF2_CMD_WRITE_FLASH_PAGE 0x0006 -struct HF2_WRITE_FLASH_PAGE_Command { - uint32_t target_addr; - uint32_t data[0]; -}; -// no result - -#define HF2_CMD_CHKSUM_PAGES 0x0007 -struct HF2_CHKSUM_PAGES_Command { - uint32_t target_addr; - uint32_t num_pages; -}; -struct HF2_CHKSUM_PAGES_Result { - uint16_t chksums[0 /* num_pages */]; -}; - -#define HF2_CMD_READ_WORDS 0x0008 -struct HF2_READ_WORDS_Command { - uint32_t target_addr; - uint32_t num_words; -}; -struct HF2_READ_WORDS_Result { - uint32_t words[0 /* num_words */]; -}; - -#define HF2_CMD_WRITE_WORDS 0x0009 -struct HF2_WRITE_WORDS_Command { - uint32_t target_addr; - uint32_t num_words; - uint32_t words[0 /* num_words */]; -}; -// no result - -#define HF2_CMD_DMESG 0x0010 -// no arguments -// results is utf8 character array - -typedef struct { - uint32_t command_id; - uint16_t tag; - uint8_t reserved0; - uint8_t reserved1; - - union { - struct HF2_WRITE_FLASH_PAGE_Command write_flash_page; - struct HF2_WRITE_WORDS_Command write_words; - struct HF2_READ_WORDS_Command read_words; - struct HF2_CHKSUM_PAGES_Command chksum_pages; - }; -} HF2_Command; - -typedef struct { - uint16_t tag; - union { - struct { - uint8_t status; - uint8_t status_info; - }; - uint16_t status16; - }; - union { - struct HF2_BININFO_Result bininfo; - uint8_t data8[0]; - uint16_t data16[0]; - uint32_t data32[0]; - }; -} HF2_Response; - -#define HF2_FLAG_SERIAL_OUT 0x80 -#define HF2_FLAG_SERIAL_ERR 0xC0 -#define HF2_FLAG_CMDPKT_LAST 0x40 -#define HF2_FLAG_CMDPKT_BODY 0x00 -#define HF2_FLAG_MASK 0xC0 -#define HF2_SIZE_MASK 63 - -#define HF2_STATUS_OK 0x00 -#define HF2_STATUS_INVALID_CMD 0x01 - -#endif