Add kernel module sources

This commit is contained in:
Michal Moskal 2017-07-25 12:15:54 +01:00
parent a159e2a668
commit 763a5c7436
17 changed files with 11255 additions and 0 deletions

2
brick/kernel/Makefile Normal file
View File

@ -0,0 +1,2 @@
obj-m += $(MOD).o

1382
brick/kernel/computil.c Normal file

File diff suppressed because it is too large Load Diff

755
brick/kernel/d_usbdev.c Normal file
View File

@ -0,0 +1,755 @@
/*
* 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 <asm/types.h>
#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 <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#ifndef PCASM
#include <linux/hrtimer.h>
#include <linux/mm.h>
#include <linux/hrtimer.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/ioport.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/hid.h>
#include <linux/utsname.h>
#include <linux/device.h>
void myReset(void);
static int dUsbInit(void);
static void dUsbExit(void);
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);
}
static const struct file_operations Device1Entries =
{
.owner = THIS_MODULE,
.read = Device1Read,
.write = Device1Write,
.mmap = Device1Mmap
};
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);
}
void myReset() {
dUsbExit();
dUsbInit();
}

File diff suppressed because it is too large Load Diff

276
brick/kernel/gadget_chips.h Normal file
View File

@ -0,0 +1,276 @@
/*
* 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 */

249
brick/kernel/source/am1808.h Executable file
View File

@ -0,0 +1,249 @@
/*
* 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 <mach/da8xx.h>
#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_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
/*
* 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_ */

View File

@ -0,0 +1,81 @@
/*
* 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_ */

View File

@ -0,0 +1,88 @@
/*
* 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_ */

View File

@ -0,0 +1,76 @@
/*
* 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_ */

View File

@ -0,0 +1,38 @@
/*
* 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_ */

1566
brick/kernel/source/lms2012.h Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/*
* 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 <Base/BasicTypes.h>
#include <VMCalls.h>
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_ */

View File

@ -0,0 +1,56 @@
/*
* 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_ */

View File

@ -0,0 +1,780 @@
/*
* 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 <asm/unaligned.h>
/* 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,
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 0
if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
LDBG(curlun, "eject attempt prevented\n");
return -EBUSY; /* "Door is locked" */
}
#endif
/* 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);
}

739
brick/kernel/usb_function.c Normal file
View File

@ -0,0 +1,739 @@
/*
* 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);
}