* Re: [GIT PULL] Generic PWM Device API
From: Greg KH @ 2011-02-28 4:45 UTC (permalink / raw)
To: Bill Gatliff; +Cc: linux-kernel, torvalds, akpm, linux-embedded
In-Reply-To: <AANLkTi=rxzrnt0QZQPJFRboSW_Fyt6zQ5S9KD4Lp=hnU@mail.gmail.com>
On Sun, Feb 27, 2011 at 09:38:38PM -0600, Bill Gatliff wrote:
> Andrew, Linus:
>
>
> The git repository described in the following pull request implements
> a generic PWM device driver API. This API is intended to eventually
> supercede the existing PWM device drivers, but during a migration
> period will coexist peacefully with them.
>
> This code has been discussed at length on the linux-embedded mailing
> list. Noteworthy threads include:
>
> v6 (final) patches:
> http://www.mail-archive.com/linux-embedded@vger.kernel.org/msg03291.html
>
> v5 patches:
> http://www.mail-archive.com/linux-embedded@vger.kernel.org/msg03279.html
>
> v4 patches:
> http://www.mail-archive.com/linux-embedded@vger.kernel.org/msg03263.html
>
>
> Thanks!
Isn't it a bit late in the -rc release cycle to pull this in now?
confused,
greg k-h
^ permalink raw reply
* [GIT PULL] Generic PWM Device API
From: Bill Gatliff @ 2011-02-28 3:38 UTC (permalink / raw)
To: linux-kernel; +Cc: torvalds, akpm, linux-embedded
Andrew, Linus:
The git repository described in the following pull request implements
a generic PWM device driver API. This API is intended to eventually
supercede the existing PWM device drivers, but during a migration
period will coexist peacefully with them.
This code has been discussed at length on the linux-embedded mailing
list. Noteworthy threads include:
v6 (final) patches:
http://www.mail-archive.com/linux-embedded@vger.kernel.org/msg03291.html
v5 patches:
http://www.mail-archive.com/linux-embedded@vger.kernel.org/msg03279.html
v4 patches:
http://www.mail-archive.com/linux-embedded@vger.kernel.org/msg03263.html
Thanks!
b.g.
---
Bill Gatliff
bgat@billgatliff.com
--------
The following changes since commit 493f3358cb289ccf716c5a14fa5bb52ab75943e5:
Merge branch 'pm-fixes' of
git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
(2011-02-25 15:15:17 -0800)
are available in the git repository at:
git://git.billgatliff.com/pwm.git linux-next
Bill Gatliff (3):
PWM: Implement a generic PWM framework
PWM: GPIO+hrtimer device emulation
PWM: Atmel PWMC driver
Documentation/pwm.txt | 277 +++++++++++++++++++++
MAINTAINERS | 8 +
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/pwm/Kconfig | 29 +++
drivers/pwm/Makefile | 7 +
drivers/pwm/atmel-pwmc.c | 494 +++++++++++++++++++++++++++++++++++++
drivers/pwm/gpio-pwm.c | 348 ++++++++++++++++++++++++++
drivers/pwm/pwm.c | 610 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pwm/pwm.h | 155 ++++++++++++
10 files changed, 1932 insertions(+), 0 deletions(-)
create mode 100644 Documentation/pwm.txt
create mode 100644 drivers/pwm/Kconfig
create mode 100644 drivers/pwm/Makefile
create mode 100644 drivers/pwm/atmel-pwmc.c
create mode 100644 drivers/pwm/gpio-pwm.c
create mode 100644 drivers/pwm/pwm.c
create mode 100644 include/linux/pwm/pwm.h
^ permalink raw reply
* Re: [PATCH 5/5] KBUS source file
From: Randy Dunlap @ 2011-02-27 20:25 UTC (permalink / raw)
To: Tony Ibbs; +Cc: Linux-embedded, Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <3CEFF9DA-16D6-43E1-A8A5-658EB1D426C7@tonyibbs.co.uk>
On Sun, 27 Feb 2011 19:26:49 +0000 Tony Ibbs wrote:
> Apologies, my fifth patch (the actual KBUS source file) appears to be
> too long - I hadn't realise the 100,000 character limit on majordomo
> messages. The file as submitted is that at:
>
> https://github.com/crazyscot/linux-2.6-kbus/blob/6cc3262bd3e28757179dd8a0d30298dfb2f70845/ipc/kbus.c
>
> If there is a better way for me to submit this, please let me know.
>
> The source is still
> Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>--
linux-kernel@vger.kernel.org allows up to 400 KB iirc, though it might be
300 KB.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* Re: [PATCH 3/5] Kconfig files and Makefile for KBUS
From: Tony Ibbs @ 2011-02-27 19:36 UTC (permalink / raw)
To: Randy Dunlap; +Cc: Linux-embedded, Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <20110227101927.3a15e535.rdunlap@xenotime.net>
On 27 Feb 2011, at 18:19, Randy Dunlap wrote:
> On Sun, 27 Feb 2011 18:11:46 +0000 Tony Ibbs wrote:
>>
>> source "kernel/Kconfig.locks"
>> +
>
> You can drop that line.
Thanks.
>> + tristate "KBUS messaging system"
>> + default m
>
> Use tabs to indent kconfig entry text, like above (not spaces).
Drat. Thank you.
> Please do not enable new configs unless they are absolutely required.
And that , of course, makes sense. Thank you again.
Tibs
^ permalink raw reply
* Re: [PATCH 5/5] KBUS source file
From: Tony Ibbs @ 2011-02-27 19:26 UTC (permalink / raw)
To: Tony Ibbs; +Cc: Linux-embedded, Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <cover.1298829754.git.tibs@tonyibbs.co.uk>
Apologies, my fifth patch (the actual KBUS source file) appears to be
too long - I hadn't realise the 100,000 character limit on majordomo
messages. The file as submitted is that at:
https://github.com/crazyscot/linux-2.6-kbus/blob/6cc3262bd3e28757179dd8a0d30298dfb2f70845/ipc/kbus.c
If there is a better way for me to submit this, please let me know.
The source is still
Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>
^ permalink raw reply
* Re: [PATCH 3/5] Kconfig files and Makefile for KBUS
From: Randy Dunlap @ 2011-02-27 18:19 UTC (permalink / raw)
To: Tony Ibbs; +Cc: Linux-embedded, Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <97f70d8d0a9026658bb08d8bb4b054124553a0cb.1298829754.git.tibs@tonyibbs.co.uk>
On Sun, 27 Feb 2011 18:11:46 +0000 Tony Ibbs wrote:
> From: Tibs <tibs@tonyibbs.co.uk>
>
> Amend the ipc Makefile.
> Add an ipc Kconfig for KBUS.
> Amend the init Kconfig appropriately.
>
> Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>
> ---
> init/Kconfig | 3 ++
> ipc/Kconfig | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ipc/Makefile | 5 +++
> 3 files changed, 107 insertions(+), 0 deletions(-)
> create mode 100644 ipc/Kconfig
>
> diff --git a/init/Kconfig b/init/Kconfig
> index c972899..a31a6fe 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -339,6 +339,8 @@ config AUDIT_TREE
> depends on AUDITSYSCALL
> select FSNOTIFY
>
> +source "ipc/Kconfig"
> +
> source "kernel/irq/Kconfig"
>
> menu "RCU Subsystem"
> @@ -1305,3 +1307,4 @@ config PADATA
> bool
>
> source "kernel/Kconfig.locks"
> +
You can drop that line.
> diff --git a/ipc/Kconfig b/ipc/Kconfig
> new file mode 100644
> index 0000000..46ebcda
> --- /dev/null
> +++ b/ipc/Kconfig
> @@ -0,0 +1,99 @@
> +config KBUS
> + tristate "KBUS messaging system"
> + default m
Use tabs to indent kconfig entry text, like above (not spaces).
Please do not enable new configs unless they are absolutely required.
> + ---help---
> + KBUS is a lightweight messaging system, particularly aimed
> + at embedded platforms. This option provides the kernel support
> + for mediating messages between client processes.
> +
> + If you want KBUS support, you should say Y here.
> +
> + This support can also be built as a module. If so, the module
> + will be called kbus.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* [PATCH 4/5] Internal header file for KBUS
From: Tony Ibbs @ 2011-02-27 18:11 UTC (permalink / raw)
To: Linux-embedded; +Cc: Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <cover.1298829754.git.tibs@tonyibbs.co.uk>
From: Tibs <tibs@tonyibbs.co.uk>
Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>
---
ipc/kbus_internal.h | 709 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 709 insertions(+), 0 deletions(-)
create mode 100644 ipc/kbus_internal.h
diff --git a/ipc/kbus_internal.h b/ipc/kbus_internal.h
new file mode 100644
index 0000000..5b711cd
--- /dev/null
+++ b/ipc/kbus_internal.h
@@ -0,0 +1,709 @@
+/* KBUS kernel module - internal definitions
+ *
+ * This is a character device driver, providing the messaging support
+ * for KBUS.
+ *
+ * This header contains the definitions used internally by kbus.c.
+ * At the moment nothing else is expected to include this file.
+ *
+ * KBUS clients should include (at least) kbus_defns.h.
+ */
+
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the KBUS Lightweight Linux-kernel mediated
+ * message system
+ *
+ * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Kynesim, Cambridge UK
+ * Tony Ibbs <tibs@tonyibbs.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * GNU Public License version 2 (the "GPL"), in which case the provisions of
+ * the GPL are applicable instead of the above. If you wish to allow the use
+ * of your version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file under either
+ * the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#ifndef _kbus_internal
+#define _kbus_internal
+
+/*
+ * KBUS can support multiple devices, as /dev/kbus<N>. These all have
+ * the same major device number, and map to differing minor device
+ * numbers. <N> will also be the minor device number, but don't rely
+ * on that for anything.
+ *
+ * When KBUS starts up, it will always setup a single device (/dev/kbus0),
+ * but it can be asked to setup more - for instance:
+ *
+ * # insmod kbus.ko kbus_num_devices=5
+ *
+ * There is also an IOCTL to allow user-space to request a new device as
+ * necessary. The hot plugging mechanisms should cause the device to appear "as
+ * if by magic".
+ *
+ * (This last means that we *could* default to setting up zero devices
+ * at module startup, and leave the user to ask for the first one, but
+ * that seems rather cruel.)
+ *
+ * We need to set a maximum number of KBUS devices (corresponding to a limit on
+ * minor device numbers). The obvious limit (corresponding to what we'd have
+ * got if we used the deprecated "register_chrdev" to setup our device) is 256,
+ * so we'll go with that.
+ */
+#define KBUS_MIN_NUM_DEVICES 1
+
+#ifdef CONFIG_KBUS_MAX_NUM_DEVICES
+#define KBUS_MAX_NUM_DEVICES CONFIG_KBUS_MAX_NUM_DEVICES
+#else
+#define KBUS_MAX_NUM_DEVICES 256
+#endif
+
+#ifndef CONFIG_KBUS_DEF_NUM_DEVICES
+#define CONFIG_KBUS_DEF_NUM_DEVICES 1
+#endif
+
+/*
+ * Our initial array sizes could arguably be made configurable
+ * for tuning, if we discover this is useful
+ */
+#define KBUS_INIT_MSG_ID_MEMSIZE 16
+#define KBUS_INIT_LISTENER_ARRAY_SIZE 8
+
+/*
+ * Setting CONFIG_KBUS_DEBUG will cause the Makefile
+ * to define DEBUG for us
+ */
+#ifdef DEBUG
+#define kbus_maybe_dbg(kbus_dev, format, args...) do { \
+ if ((kbus_dev)->verbose) \
+ (void) dev_dbg((kbus_dev)->dev, format, ## args); \
+} while (0)
+#else
+#define kbus_maybe_dbg(kbus_dev, format, args...) ((void)0)
+#endif
+
+/*
+ * This is really only directly useful if CONFIG_KBUS_DEBUG is on
+ */
+#ifdef CONFIG_KBUS_DEBUG_DEFAULT_VERBOSE
+#define KBUS_DEFAULT_VERBOSE_SETTING true
+#else
+#define KBUS_DEFAULT_VERBOSE_SETTING false
+#endif
+
+/* ========================================================================= */
+
+/* We need a way of remembering message bindings */
+struct kbus_message_binding {
+ struct list_head list;
+ struct kbus_private_data *bound_to; /* who we're bound to */
+ u32 bound_to_id; /* but the id is often useful */
+ u32 is_replier; /* bound as a replier */
+ u32 name_len;
+ char *name; /* the message name */
+};
+
+/*
+ * For both keeping track of requests sent (to which we still want replies)
+ * and replies read (to which we haven't yet sent a reply), we need some
+ * means of remembering message ids. Since I'd rather not worry the rest of
+ * the code with how this is implemented (which is code for "I'll implement
+ * it very simply and worry about making it efficient/scalable later"), and
+ * since we always want to remember both the message ids and also how many
+ * there are, it seems sensible to bundle this up in its own datastructure.
+ */
+struct kbus_msg_id_mem {
+ u32 count; /* Number of entries in use */
+ u32 size; /* Actual size of the array */
+ u32 max_count; /* Max 'count' we've had */
+ /*
+ * An array is probably the worst way to store a list of message ids,
+ * but it's *very simple*, and should work OK for a smallish number of
+ * message ids. So it's a place to start...
+ *
+ * Note the array may have "unused" slots, signified by message id {0:0}
+ */
+ struct kbus_msg_id *ids;
+};
+
+/* An item in the list of requests that a Ksock has not yet replied to */
+struct kbus_unreplied_item {
+ struct list_head list;
+ struct kbus_msg_id id; /* the request's id */
+ u32 from; /* the sender's id */
+ struct kbus_name_ptr *name_ref; /* and its name... */
+ u32 name_len;
+};
+
+/*
+ * The parts of a message being written to KBUS (via kbus_write[_parts]),
+ * or read by the user (via kbus_read) are:
+ *
+ * * the user-space message header - as in 'struct kbus_message_header'
+ *
+ * from which we copy various items into our own internal message header.
+ *
+ * For a "pointy" message, that is all there is.
+ *
+ * For an "entire" message, this is then followed by:
+ *
+ * * the message name
+ * * padding to bring that up to a NULL terminator and then a 4-byte boundary.
+ *
+ * If the "entire" message has data, then this is followed by:
+ *
+ * * N data parts (all but the last of size PART_LEN)
+ * * padding to bring that up to a 4-byte boundary.
+ *
+ * and finally, whether there was data or not:
+ *
+ * * the final end guard.
+ *
+ * Remember that kbus_read always delivers an "entire" message.
+ */
+enum kbus_msg_parts {
+ KBUS_PART_HDR = 0,
+ KBUS_PART_NAME,
+ KBUS_PART_NPAD,
+ KBUS_PART_DATA,
+ KBUS_PART_DPAD,
+ KBUS_PART_FINAL_GUARD
+};
+/* N.B. New message parts require switch cases in kbus_msg_part_name()
+ * and kbus_write_parts().
+ */
+
+#define KBUS_NUM_PARTS (KBUS_PART_FINAL_GUARD+1)
+
+/*
+ * Replier typing.
+ * The higher the replier type, the more specific it is.
+ * We trust the binding mechanisms not to have created two replier
+ * bindings of the same type for the same name (so we shan't, for
+ * example, get '$.Fred.*' bound as replier twice).
+ */
+
+enum kbus_replier_type {
+ UNSET = 0,
+ WILD_STAR,
+ WILD_PERCENT,
+ SPECIFIC
+};
+
+/*
+ * A reference counting wrapper for message data
+ *
+ * If 'as_pages' is false, then the data is stored as a single kmalloc'd
+ * entity, pointed to by 'parts[0]'. In this case, 'num_parts' will be 1,
+ * and 'last_page_len' will be the size of the allocated data.
+ *
+ * If 'as_pages' is true, then the data is stored as 'num_parts' pages, each
+ * pointed to by 'parts[n]'. The last page should be treated as being size
+ * 'last_page_len' (even if the implementation is not enforcing this). All
+ * other pages are of size PART_LEN.
+ *
+ * In either case, 'lengths[n]' is a "fill counter" for how many bytes of data
+ * are actually being stored in page 'n'. Once the data is all in place, this
+ * should be equal to PART_LEN or 'last_page_len' as appropriate.
+ *
+ * 'refcount' is a stanard kernel reference count for the data - when it reaches
+ * 0, everything (the parts, the arrays and the datastructure) gets freed.
+ */
+struct kbus_data_ptr {
+ int as_pages;
+ unsigned num_parts;
+ unsigned long *parts;
+ unsigned *lengths;
+ unsigned last_page_len;
+ struct kref refcount;
+};
+
+/*
+ * A reference counting wrapper for message names
+ *
+ * RATIONALE:
+ *
+ * When a message name is copied from user space, we take our first copy.
+ *
+ * In order to send a message to a Ksock, we use kbus_push_message(), which
+ * takes a copy of the message for each recipient.
+ *
+ * We also take a copy of the message name for our list of messages that have
+ * been read but not replied to.
+ *
+ * It makes sense to copy the message header, because the contents thereof are
+ * changed according to the particular recipient.
+ *
+ * Copying the message data (if any) is handled by the kbus_data_ptr, above,
+ * which provides reference counting. This makes sense because message data may
+ * be large.
+ *
+ * If we only have one recipient, copying the message name is not a big issue,
+ * but if there are many, we would prefer not to make many copies of the
+ * string. It is, perhaps, worth keeping a dictionary of message names. and
+ * referring to the name in that - but that's not an incremental change from
+ * the "simple copying" state we start from.
+ *
+ * The simplest change to make, which may have some benefit, is to reference
+ * count the names for an individual message, as is done for the message data.
+ *
+ * If we have a single recipient, we will have copied the string from user
+ * space, and also created the kbus_name_ptr datastructure - an overhead of 8
+ * bytes. However, when we copy the message for the recipient, we do not need
+ * to copy the message name, so if the message name is more than 8 bytes, we
+ * have immediately made a gain (and experience shows that message names tend
+ * to be at least that long).
+ *
+ * As soon as we have more than one recipient, it becomes extremely likely that
+ * we have saved space, and we will definitely have saved allocations which
+ * could be fragmenting memory. So it sounds like a good thing to try.
+ *
+ * Also, if I later on want to store a hash code for the string (hoping to
+ * speed up comparisons), the new datastructure gives me somewhere to put it...
+ */
+struct kbus_name_ptr {
+ char *name;
+ struct kref refcount;
+};
+
+/*
+ * When the user reads a message from us, they receive a kbus_entire_message
+ * structure.
+ *
+ * When the user writes a message to us, they write a "pointy" message, using
+ * the kbus_message_header structure, or an "entire" message, using the
+ * kbus_entire_message structure.
+ *
+ * Within the kernel, all messages are held as "pointy" messages, but instead
+ * of direct pointers to the message name and data, we use reference counted
+ * pointers.
+ *
+ * Rather than overload the 'name' and 'data' pointer fields, with all the
+ * danger of getting it wrong that that implies, it seems simpler to have our
+ * own, internal to the kernel, clone of the datastructure, but with these
+ * fields defined correctly...
+ *
+ * Hmm. If we have the name and data references, perhaps we should move the
+ * name and data *lengths* into those same.
+ */
+
+struct kbus_msg {
+ struct kbus_msg_id id; /* Unique to this message */
+ struct kbus_msg_id in_reply_to; /* Which message this is a reply to */
+ u32 to; /* 0 (empty) or a replier id */
+ u32 from; /* 0 (KBUS) or the sender's id */
+ struct kbus_orig_from orig_from; /* Cross-network linkage */
+ struct kbus_orig_from final_to; /* Cross-network linkage */
+ u32 extra; /* ignored field - future proofing */
+ u32 flags; /* Message type/flags */
+ u32 name_len; /* Message name's length, in bytes */
+ u32 data_len; /* Message length, also in bytes */
+ struct kbus_name_ptr *name_ref;
+ struct kbus_data_ptr *data_ref;
+};
+
+/*
+ * The current message that the user is reading (with kbus_read())
+ *
+ * If 'msg' is NULL, then the data structure is "empty" (i.e., there is no
+ * message being read).
+ */
+struct kbus_read_msg {
+ struct kbus_entire_message user_hdr; /* the header for user space */
+
+ struct kbus_msg *msg; /* the internal message */
+ char *parts[KBUS_NUM_PARTS];
+ unsigned lengths[KBUS_NUM_PARTS];
+ int which; /* The current item */
+ u32 pos; /* How far they've read in it */
+ /*
+ * If the current item is KBUS_PART_DATA then we 'ref_data_index' is
+ * which part of the data we're in, and 'pos' is how far we are through
+ * that particular item.
+ */
+ u32 ref_data_index;
+};
+
+/*
+ * See kbus_write_parts() for how this data structure is actually used.
+ *
+ * If 'msg' is NULL, then the data structure is "empty" (i.e., there is no
+ * message being written).
+ *
+ * * 'is_finished' is true when we've got all the bytes for our message,
+ * and thus don't want any more. It's an error for the user to try to
+ * write more message after it is finished.
+ *
+ * For a "pointy" message, this is set immediately after the message header
+ * end guard is finished (the message name and any data aren't "pulled in"
+ * until the user does SEND). For an "entire" message, this is set after the
+ * final end guard is finished (so we will have the message name and any data
+ * in memory).
+ *
+ * * 'pointers_are_local' is true if the message's name and data have been
+ * transferred to kernel space (as reference counted entities), and false
+ * if they are (still) in user space.
+ *
+ * * 'hdr' is the message header, the shorter in-kernel version.
+ *
+ * * 'which' indicates which part of the message we think we're being given
+ * bytes for, from KBUS_PART_HDR through to (for an "entire" message)
+ * KBUS_PART_FINAL_GUARD.
+ * * 'pos' is the index of the next byte within the current part of whatever
+ * we're working on, as indicated by 'which'. Note that for message data,
+ * this is the index within the whole of the data (not the index within a
+ * data part).
+ *
+ * * If we're reading an "entire" message, then the message name gets written
+ * to 'ref_name', which is a reference-counted string. This is allocated to
+ * the correct size/shape for the entire message name, after the head has
+ * been read.
+ *
+ * The intention is that, if 'ref_name' is non-NULL, it should be legal
+ * to call 'kbus_lower_name_ref()' on it, to free its contents.
+ *
+ * * Similarly, 'ref_data' is reference-counted data, again allocated to the
+ * correct size/shape for the entire message data length, after the header
+ * has been read. The 'length' for each part is used to indicate how far
+ * through that part we have populated with bytes.
+ *
+ * The intention is that, if 'ref_data' is non-NULL, it should be legal
+ * to call 'kbus_lower_data_ref()' on it, to free its contents.
+ *
+ * 'ref_data_index' is then the index (starting at 0) of the referenced
+ * data part that we are populating.
+ */
+struct kbus_write_msg {
+ struct kbus_entire_message user_msg; /* from user space */
+ struct kbus_msg *msg; /* our version of it */
+
+ u32 is_finished;
+ u32 pointers_are_local;
+ u32 guard; /* Whichever guard we're reading */
+ char *user_name_ptr; /* User space name */
+ void *user_data_ptr; /* User space data */
+ enum kbus_msg_parts which;
+ u32 pos;
+ struct kbus_name_ptr *ref_name;
+ struct kbus_data_ptr *ref_data;
+ u32 ref_data_index;
+};
+
+/*
+ * The data for an unsent Replier Bind Event (in the unsent_unbind_msg_list)
+ *
+ * Note that 'binding' may theroretically be NULL (although I don't think this
+ * should ever actually happen).
+ */
+struct kbus_unsent_message_item {
+ struct list_head list;
+ struct kbus_private_data *send_to; /* who we want to send it to */
+ u32 send_to_id; /* but the id is often useful */
+ struct kbus_msg *msg; /* the message itself */
+ struct kbus_message_binding *binding; /* and why we remembered it */
+};
+
+/*
+ * This is the data for an individual Ksock
+ *
+ * Each time we open /dev/kbus<n>, we need to remember a unique id for
+ * our file-instance. Using 'filp' might work, but it's not something
+ * we have control over, and in particular, if the file is closed and
+ * then reopened, there's no guarantee that a particular value of 'filp'
+ * won't be used again. A simple serial number is safer.
+ *
+ * Each such "opening" also has a message queue associated with it. Any
+ * messages this "opening" has declared itself a listener (or replier)
+ * for will be added to that queue.
+ *
+ * 'id' is the unique id for this file descriptor - it enables stateful message
+ * transtions, etc. It is local to the particular KBUS device.
+ *
+ * 'last_msg_id_sent' is the message id of the last message that was
+ * (successfully) written to this file descriptor. It is needed when
+ * constructing a reply.
+ *
+ * We have a queue of messages waiting for us to read them, in 'message_queue'.
+ * 'message_count' is how many messages are in the queue, and 'max_messages'
+ * is an indication of how many messages we shall allow in the queue.
+ *
+ * Note that, however a message was originally sent to us, messages held
+ * internally are always a message header plus pointers to a message name and
+ * (optionally) message data. See kbus_send() for details.
+ */
+struct kbus_private_data {
+ struct list_head list;
+ struct kbus_dev *dev; /* Which device we are on */
+ u32 id; /* Our own id */
+ struct kbus_msg_id last_msg_id_sent; /* As it says - see above */
+ u32 message_count; /* How many messages for us */
+ u32 max_messages; /* How many messages allowed */
+ struct list_head message_queue; /* Messages for us */
+
+ /*
+ * It's useful (for /proc/kbus/bindings) to remember the PID of the
+ * current process
+ */
+ pid_t pid;
+
+ /* Wait for something to appear in the message_queue */
+ wait_queue_head_t read_wait;
+
+ /* The message currently being read by the user */
+ struct kbus_read_msg read;
+
+ /* The message currently being written by the user */
+ struct kbus_write_msg write;
+
+ /* Are we currently sending that message? */
+ int sending;
+
+ /*
+ * Each request we send should (eventually) generate us a reply, or
+ * at worst a status message from KBUS itself telling us there isn't
+ * going to be one. So we need to ensure that there is room in our
+ * (as the sender) message queue to receive all/any such.
+ *
+ * Note that this *also* allows SEND to forbid sending a Reply to a
+ * Request that we did not receive (or to which we have already
+ * replied)
+ */
+ struct kbus_msg_id_mem outstanding_requests;
+
+ /*
+ * If we are a replier for a message, then KBUS wants to ensure
+ * that a reply is *definitely* made. If we release ourselves, then
+ * we're clearly not going to reply to any requests that we have
+ * read but not replied to, and KBUS would like to generate a status
+ * message for each such. So we need a list of the information needed
+ * to form such Status/Reply messages.
+ *
+ * (Thus we don't need the whole of the original message, since
+ * we're only *really* needing its name, its id and who its
+ * from -- given which its easiest just to keep the parts we
+ * *do* need, and ignore the data.)
+ *
+ * It was decided not to place a limit on the size of this list.
+ * Its size is limited by the ability of sender(s) to send
+ * requests, which in turn is limited by the the number of slots
+ * they can reserve for the replies to those requests in their
+ * own message queues.
+ *
+ * If a limit was imposed, then we would also need to stop a sender
+ * sending a request because the replier has too many replies
+ * outstanding (for instance, because it has gone to sleep). But
+ * then we'd assume that it is not responding to messages in
+ * general, and so its message queue would fill up, and that
+ * should be sufficient protection.
+ */
+ struct list_head replies_unsent;
+ u32 num_replies_unsent;
+ u32 max_replies_unsent;
+
+ /*
+ * Managing which messages a replier may reply to
+ * ----------------------------------------------
+ * We need to police replying, such that a replier may only reply
+ * to requests that it has received (where "received" means "had
+ * placed into its message queue", because KBUS must reply for us
+ * if the particular Ksock is not going to).
+ *
+ * It is possible to do this using either the 'outstanding_requests'
+ * or the 'replies_unsent' list.
+ *
+ * Using the 'outstanding_requests' list means that when a replier
+ * wants to send a reply, it needs to look up who the original-sender
+ * is (from its Ksock id, in the "from" field of the message), and
+ * check against that. This is a bit inefficient.
+ *
+ * Using the 'replies_unsent' list means that when a replier wants
+ * to send a reply, it just needs to find the right message stub
+ * in said 'replies_unsent' list, and check that the reply *does*
+ * match the original request. This may be more efficient, depending.
+ *
+ * In fact, the 'outstanding_requests' list is used, simply because
+ * it was implemented first.
+ */
+
+ /*
+ * By default, if a Ksock binds to a message name as both Replier and
+ * Listener (typically by binding to a specific message name as Replier
+ * and to a wildcard including it as Listener), and a Reqest of that
+ * name is sent to that Ksock, it will get the message once as Replier
+ * (marked "WANT_YOU_TO_REPLY"), and once as listener.
+ *
+ * This is technically sensible, but can be irritating to the end user
+ * who really often only wants to receive the message once.
+ *
+ * If "messages_only_once" is set, then when a message is about to be
+ * put onto a Ksocks message queue, it will only be added if it (i.e.,
+ * a message with the same id) has not already just been added. This
+ * is safe because Requests to the specific Replier are always dealt
+ * with first.
+ *
+ * As a side-effect, which I think also makes sense, this will also
+ * mean that if a Listener has bound to the same message name multiple
+ * times (as a Listener), then they will only get the message once.
+ */
+ int messages_only_once;
+ /*
+ * Messages can be added to either end of our message queue (i.e.,
+ * depending on whether they're urgent or not). This means that the
+ * "only once" mechanism needs to check both ends of the queue (which
+ * is a pain). Or we can just remember the message id of the last
+ * message pushed onto the queue. Which is much simpler.
+ */
+ struct kbus_msg_id msg_id_just_pushed;
+
+ /*
+ * If this flag is set, then we may have outstanding Replier Unbound
+ * Event messages (kept on a list on our device). These must be read
+ * before any "normal" messages (on our message_queue) get read.
+ */
+ int maybe_got_unsent_unbind_msgs;
+};
+
+/* What is a sensible number for the default maximum number of messages? */
+#ifndef CONFIG_KBUS_DEF_MAX_MESSAGES
+#define CONFIG_KBUS_DEF_MAX_MESSAGES 100
+#endif
+
+/*
+ * What about the maximum number of unsent unbind event messages?
+ * This may want to be quite large, to allow for Limpets with momentary
+ * network outages.
+ *
+ * The default value is probably too small, but experimantation is
+ * needed to determine a more sensible value.
+ */
+#ifndef CONFIG_KBUS_MAX_UNSENT_UNBIND_MESSAGES
+#define CONFIG_KBUS_MAX_UNSENT_UNBIND_MESSAGES 1000
+#endif
+
+/* Information belonging to each /dev/kbus<N> device */
+struct kbus_dev {
+ struct cdev cdev; /* Character device data */
+ struct device *dev; /* Our very selves */
+
+ u32 index; /* Which /dev/kbus<n> device we are */
+
+ /*
+ * The Big Lock
+ * We use a single mutex for all purposes, and all locking is done
+ * at the "top level", i.e., in the externally called functions.
+ * This simplifies the design of the internal (list processing,
+ * etc.) functions, at the possible cost of making interaction
+ * with KBUS, in general, slower.
+ *
+ * On the other hand, we favour reliable over fast.
+ */
+ struct mutex mux;
+
+ /* Who has bound to receive which messages in what manner */
+ struct list_head bound_message_list;
+
+ /*
+ * The actual Ksock entries (one per 'open("/dev/kbus<n>")')
+ * This is to allow us to find the 'kbus_private_data' instances,
+ * so that we can get at all the message queues. The details of
+ * how we do this are *definitely* going to change...
+ */
+ struct list_head open_ksock_list;
+
+ /* Has one of our Ksocks made space available in its message queue? */
+ wait_queue_head_t write_wait;
+
+ /*
+ * Each open file descriptor needs an internal id - this is used
+ * when binding messages to listeners, but is also needed when we
+ * want to reply. We reserve the id 0 as a special value ("none").
+ */
+ u32 next_ksock_id;
+
+ /*
+ * Every message sent has a unique id (again, unique per device).
+ */
+ u32 next_msg_serial_num;
+
+ /* Are we wanting debugging messages? */
+ u32 verbose;
+
+ /*
+ * Are we wanting to send a synthetic message for each Replier
+ * bind/unbind? */
+ u32 report_replier_binds;
+
+ /*
+ * If Replier (un)bind events have been requested, then when
+ * kbus_release is called, a message must be sent for each Replier that
+ * is (of necessity) unbound from the Ksock being released. For a
+ * normal unbound, if any of the Repliers doesn't have room in its
+ * message queue for such an event, then the unbind fails with -EAGAIN.
+ * This isn't acceptable for kbus_release (apart from anything else,
+ * the release might be due to the original program falling over).
+ * It's not acceptable to fail to send the messages (that's a general
+ * KBUS principle).
+ *
+ * The only sensible solution seems to be to put the messages we'd
+ * like to have sent onto a set-aside list, and mark each recipient
+ * as having messages thereon. Then, each time a Ksock looks for a
+ * new message, it should first check to see if it might have one
+ * on the set-aside list, and if it does, read that instead.
+ *
+ * Once we're doing this, though, we need some limit on how big that
+ * set-aside list may grow (to allow for user processes that keep
+ * binding and falling over!). When the list gets "too long", we set a
+ * "gone tragically wrong" flag, and instead of adding more unbind
+ * events, we instead add a single "gone tragically wrong" message for
+ * each Ksock. We don't revert to remembering unbind events again until
+ * the list has been emptied.
+ */
+ struct list_head unsent_unbind_msg_list;
+ u32 unsent_unbind_msg_count;
+ int unsent_unbind_is_tragic;
+};
+
+/*
+ * Each entry in a message queue holds a single message, and a pointer to
+ * the message name binding that caused it to be added to the list. This
+ * makes it simple to remove messages from the queue if the message name
+ * binding is unbound. The binding shall be NULL for:
+ *
+ * * Replies
+ * * KBUS "synthetic" messages, which are also (essentialy) Replies
+ */
+struct kbus_message_queue_item {
+ struct list_head list;
+ struct kbus_msg *msg;
+ struct kbus_message_binding *binding;
+};
+
+/* The sizes of the parts in our reference counted data */
+#define KBUS_PART_LEN PAGE_SIZE
+#define KBUS_PAGE_THRESHOLD (PAGE_SIZE >> 1)
+
+#endif /* _kbus_internal */
--
1.7.1
^ permalink raw reply related
* [PATCH 3/5] Kconfig files and Makefile for KBUS
From: Tony Ibbs @ 2011-02-27 18:11 UTC (permalink / raw)
To: Linux-embedded; +Cc: Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <cover.1298829754.git.tibs@tonyibbs.co.uk>
From: Tibs <tibs@tonyibbs.co.uk>
Amend the ipc Makefile.
Add an ipc Kconfig for KBUS.
Amend the init Kconfig appropriately.
Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>
---
init/Kconfig | 3 ++
ipc/Kconfig | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ipc/Makefile | 5 +++
3 files changed, 107 insertions(+), 0 deletions(-)
create mode 100644 ipc/Kconfig
diff --git a/init/Kconfig b/init/Kconfig
index c972899..a31a6fe 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -339,6 +339,8 @@ config AUDIT_TREE
depends on AUDITSYSCALL
select FSNOTIFY
+source "ipc/Kconfig"
+
source "kernel/irq/Kconfig"
menu "RCU Subsystem"
@@ -1305,3 +1307,4 @@ config PADATA
bool
source "kernel/Kconfig.locks"
+
diff --git a/ipc/Kconfig b/ipc/Kconfig
new file mode 100644
index 0000000..46ebcda
--- /dev/null
+++ b/ipc/Kconfig
@@ -0,0 +1,99 @@
+config KBUS
+ tristate "KBUS messaging system"
+ default m
+ ---help---
+ KBUS is a lightweight messaging system, particularly aimed
+ at embedded platforms. This option provides the kernel support
+ for mediating messages between client processes.
+
+ If you want KBUS support, you should say Y here.
+
+ This support can also be built as a module. If so, the module
+ will be called kbus.
+
+if KBUS
+
+config KBUS_DEBUG
+ bool "Make KBUS debugging messages available"
+ default y
+ ---help---
+ This is the master switch for KBUS debug kernel messages -
+ if turned off, all debug messages will be compiled out.
+
+ In order for debugging messages to be emitted, they must
+ be enabled per-device with the KBUS_IOC_VERBOSE ioctl,
+ or by default by CONFIG_KBUS_DEBUG_DEFAULT_VERBOSE.
+
+ If unsure, say Y.
+
+config KBUS_DEBUG_DEFAULT_VERBOSE
+ bool "Output KBUS debug messages by default"
+ depends on KBUS_DEBUG
+ default n
+ ---help---
+ This switch is the default setting for whether KBUS devices will
+ emit debugging messages. Note that debug messages may be turned
+ on and off per-device at runtime with the KBUS_IOC_VERBOSE ioctl.
+
+ If unsure, say N.
+
+config KBUS_DEF_NUM_DEVICES
+ int "Number of KBUS devices to auto-create"
+ default 1
+ range 1 KBUS_MAX_NUM_DEVICES
+ ---help---
+ This specifies the number of KBUS devices that will be automatically
+ created when the kbus subsystem initialises (when the module is
+ is loaded or the kernel booted, as appropriate).
+
+ If kbus is built as a module, this number may also be given as a
+ parameter, for example kbus_num_devices=5.
+
+config KBUS_MAX_NUM_DEVICES
+ int "Maximum number of KBUS devices"
+ default 256
+ range 1 2147483647
+ # We don't impose a limit on the max, so if you've got enough
+ # RAM the only practical limit will be the (int) minor count
+ # passed to __register_chrdev_region.
+ ---help---
+ Specify the maximum number of KBUS devices to support.
+ Note that this setting controls the size of an array of pointers
+ to in-kernel kbus structs; reducing it only saves a tiny amount
+ of RAM.
+
+config KBUS_DEF_MAX_MESSAGES
+ int "Default KBUS message queue size limit"
+ default 100
+ range 1 2147483647
+ ---help---
+ Specify the default recipient message queue size limit.
+ This default is applied to all recipients (clients) whenever they
+ open or reopen a KBUS device node.
+
+ Clients sending messages may specify their desired behaviour in
+ the event that any of the recipient(s)' message queues is full;
+ if a sender's own queue is full, it may not send a message
+ flagged as a Request. Refer to the documentation ("Queues filling
+ up") for details.
+
+ Clients may change their own queue size limits at any time with the
+ KBUS_IOC_MAXMSGS ioctl.
+
+config KBUS_MAX_UNSENT_UNBIND_MESSAGES
+ int "Maximum number of unsent KBUS unbind event messages"
+ default 1000
+ range 1 2147483647
+ ---help---
+ KBUS devices may request (by ioctl) that they want to receive
+ notifications when listeners unbind. If such a notification happens
+ at a time when the device's message queue is full, it is instead
+ saved internally and delivered later. This setting limits the number
+ of messages which may be queued internally in that way; if the
+ limit is reached, a special "there were more unbind events than
+ we were able to deliver" message is queued for that listener,
+ and no more internal events are sent to them until that message
+ has been delivered.
+
+endif # KBUS
+
diff --git a/ipc/Makefile b/ipc/Makefile
index 9075e17..3b330eb 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -2,6 +2,10 @@
# Makefile for the linux ipc.
#
+ifeq ($(CONFIG_KBUS_DEBUG),y)
+ CFLAGS_kbus.o = -DDEBUG
+endif
+
obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o syscall.o
obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
@@ -9,4 +13,5 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
obj-$(CONFIG_IPC_NS) += namespace.o
obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
+obj-$(CONFIG_KBUS) += kbus.o
--
1.7.1
^ permalink raw reply related
* [PATCH 2/5] External header file for KBUS
From: Tony Ibbs @ 2011-02-27 18:11 UTC (permalink / raw)
To: Linux-embedded; +Cc: Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <cover.1298829754.git.tibs@tonyibbs.co.uk>
From: Tibs <tibs@tonyibbs.co.uk>
Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>
---
include/linux/kbus_defns.h | 666 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 666 insertions(+), 0 deletions(-)
create mode 100644 include/linux/kbus_defns.h
diff --git a/include/linux/kbus_defns.h b/include/linux/kbus_defns.h
new file mode 100644
index 0000000..82779a6
--- /dev/null
+++ b/include/linux/kbus_defns.h
@@ -0,0 +1,666 @@
+/* Kbus kernel module external headers
+ *
+ * This file provides the definitions (datastructures and ioctls) needed to
+ * communicate with the KBUS character device driver.
+ */
+
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the KBUS Lightweight Linux-kernel mediated
+ * message system
+ *
+ * The Initial Developer of the Original Code is Kynesim, Cambridge UK.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Kynesim, Cambridge UK
+ * Tony Ibbs <tibs@tonyibbs.co.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * GNU Public License version 2 (the "GPL"), in which case the provisions of
+ * the GPL are applicable instead of the above. If you wish to allow the use
+ * of your version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file under either
+ * the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#ifndef _kbus_defns
+#define _kbus_defns
+
+#if !__KERNEL__ && defined(__cplusplus)
+extern "C" {
+#endif
+
+#if __KERNEL__
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#else
+#include <stdint.h>
+#include <sys/ioctl.h>
+#endif
+
+/*
+ * A message id is made up of two fields.
+ *
+ * If the network id is 0, then it is up to us (KBUS) to assign the
+ * serial number. In other words, this is a local message.
+ *
+ * If the network id is non-zero, then this message is presumed to
+ * have originated from another "network", and we preserve both the
+ * network id and the serial number.
+ *
+ * The message id {0,0} is special and reserved (for use by KBUS).
+ */
+struct kbus_msg_id {
+ __u32 network_id;
+ __u32 serial_num;
+};
+
+/*
+ * kbus_orig_from is used for the "originally from" and "finally to" ids
+ * in the message header. These in turn are used when messages are
+ * being sent between KBUS systems (via KBUS "Limpets"). KBUS the kernel
+ * module transmits them, unaltered, but does not use them (although
+ * debug messages may report them).
+ *
+ * An "originally from" or "finally to" id is made up of two fields, the
+ * network id (which indicates the Limpet, if any, that originally gated the
+ * message), and a local id, which is the Ksock id of the original sender
+ * of the message, on its local KBUS.
+ *
+ * If the network id is 0, then the "originally from" id is not being used.
+ *
+ * Limpets and these fields are discussed in more detail in the userspace
+ * KBUS documentation - see http://kbus-messaging.org/ for pointers to
+ * more information.
+ */
+struct kbus_orig_from {
+ __u32 network_id;
+ __u32 local_id;
+};
+
+/* When the user asks to bind a message name to an interface, they use: */
+struct kbus_bind_request {
+ __u32 is_replier; /* are we a replier? */
+ __u32 name_len;
+ char *name;
+};
+
+/* When the user requests the id of the replier to a message, they use: */
+struct kbus_bind_query {
+ __u32 return_id;
+ __u32 name_len;
+ char *name;
+};
+
+/* When the user writes/reads a message, they use: */
+struct kbus_message_header {
+ /*
+ * The guards
+ * ----------
+ *
+ * * 'start_guard' is notionally "Kbus", and 'end_guard' (the 32 bit
+ * word after the rest of the message datastructure) is notionally
+ * "subK". Obviously that depends on how one looks at the 32-bit
+ * word. Every message datastructure shall start with a start guard
+ * and end with an end guard.
+ *
+ * These provide some help in checking that a message is well formed,
+ * and in particular the end guard helps to check for broken length
+ * fields.
+ *
+ * - 'id' identifies this particular message.
+ *
+ * When a user writes a new message, they should set this to {0,0}.
+ * KBUS will then set a new message id for the message.
+ *
+ * When a user reads a message, this will have been set by KBUS.
+ *
+ * When a user replies to a message, they should copy this value
+ * into the 'in_reply_to' field, so that the recipient will know
+ * what message this was a reply to.
+ *
+ * - 'in_reply_to' identifies the message this is a reply to.
+ *
+ * This shall be set to {0,0} unless this message *is* a reply to a
+ * previous message. In other words, if this value is non-0, then
+ * the message *is* a reply.
+ *
+ * - 'to' is who the message is to be sent to.
+ *
+ * When a user writes a new message, this should normally be set
+ * to {0,0}, meaning "anyone listening" (but see below if "state"
+ * is being maintained).
+ *
+ * When replying to a message, it shall be set to the 'from' value
+ * of the orginal message.
+ *
+ * When constructing a request message (a message wanting a reply),
+ * the user can set it to a specific replier id, to produce a stateful
+ * request. This is normally done by copying the 'from' of a previous
+ * Reply from the appropriate replier. When such a message is sent,
+ * if the replier bound (at that time) does not have that specific
+ * id, then the send will fail.
+ *
+ * Note that if 'to' is set, then 'orig_from' should also be set.
+ *
+ * - 'from' indicates who sent the message.
+ *
+ * When a user is writing a new message, they should set this
+ * to {0,0}.
+ *
+ * When a user is reading a message, this will have been set
+ * by KBUS.
+ *
+ * When a user replies to a message, the reply should have its
+ * 'to' set to the original messages 'from', and its 'from' set
+ * to {0,0} (see the "hmm" caveat under 'to' above, though).
+ *
+ * - 'orig_from' and 'final_to' are used when Limpets are mediating
+ * KBUS messages between KBUS devices (possibly on different
+ * machines). See the description by the datastructure definition
+ * above. The KBUS kernel preserves and propagates their values,
+ * but does not alter or use them.
+ *
+ * - 'extra' is currently unused, and KBUS will set it to zero.
+ * Future versions of KBUS may treat it differently.
+ *
+ * - 'flags' indicates the type of message.
+ *
+ * When a user writes a message, this can be used to indicate
+ * that:
+ *
+ * * the message is URGENT
+ * * a reply is wanted
+ *
+ * When a user reads a message, this indicates if:
+ *
+ * * the message is URGENT
+ * * a reply is wanted
+ *
+ * When a user writes a reply, this field should be set to 0.
+ *
+ * The top half of the 'flags' is not touched by KBUS, and may
+ * be used for any purpose the user wishes.
+ *
+ * - 'name_len' is the length of the message name in bytes.
+ *
+ * This must be non-zero.
+ *
+ * - 'data_len' is the length of the message data in bytes. It may be
+ * zero if there is no data.
+ *
+ * - 'name' is a pointer to the message name. This should be null
+ * terminated, as is the normal case for C strings.
+ *
+ * NB: If this is zero, then the name will be present, but after
+ * the end of this datastructure, and padded out to a multiple of
+ * four bytes (see kbus_entire_message). When doing this padding,
+ * remember to allow for the terminating null byte. If this field is
+ * zero, then 'data' shall also be zero.
+ *
+ * - 'data' is a pointer to the data. If there is no data (if
+ * 'data_len' is zero), then this shall also be zero. The data is
+ * not touched by KBUS, and may include any values.
+ *
+ * NB: If this is zero, then the data will occur immediately
+ * after the message name, padded out to a multiple of four bytes.
+ * See the note for 'name' above.
+ *
+ */
+ __u32 start_guard;
+ struct kbus_msg_id id; /* Unique to this message */
+ struct kbus_msg_id in_reply_to; /* Which message this is a reply to */
+ __u32 to; /* 0 (empty) or a replier id */
+ __u32 from; /* 0 (KBUS) or the sender's id */
+ struct kbus_orig_from orig_from;/* Cross-network linkage */
+ struct kbus_orig_from final_to; /* Cross-network linkage */
+ __u32 extra; /* ignored field - future proofing */
+ __u32 flags; /* Message type/flags */
+ __u32 name_len; /* Message name's length, in bytes */
+ __u32 data_len; /* Message length, also in bytes */
+ char *name;
+ void *data;
+ __u32 end_guard;
+};
+
+#define KBUS_MSG_START_GUARD 0x7375624B
+#define KBUS_MSG_END_GUARD 0x4B627573
+
+/*
+ * When a message is returned by 'read', it is actually returned using the
+ * following datastructure, in which:
+ *
+ * - 'header.name' will point to 'rest[0]'
+ * - 'header.data' will point to 'rest[(header.name_len+3)/4]'
+ *
+ * followed by the name (padded to 4 bytes, remembering to allow for the
+ * terminating null byte), followed by the data (padded to 4 bytes) followed by
+ * (another) end_guard.
+ */
+struct kbus_entire_message {
+ struct kbus_message_header header;
+ __u32 rest[];
+};
+
+/*
+ * We limit a message name to at most 1000 characters (some limit seems
+ * sensible, after all)
+ */
+#define KBUS_MAX_NAME_LEN 1000
+
+/*
+ * The length (in bytes) of the name after padding, allowing for a terminating
+ * null byte.
+ */
+#define KBUS_PADDED_NAME_LEN(name_len) (4 * ((name_len + 1 + 3) / 4))
+
+/*
+ * The length (in bytes) of the data after padding
+ */
+#define KBUS_PADDED_DATA_LEN(data_len) (4 * ((data_len + 3) / 4))
+
+/*
+ * Given name_len (in bytes) and data_len (in bytes), return the
+ * length of the appropriate kbus_entire_message_struct, in bytes
+ *
+ * Note that we're allowing for a zero byte after the end of the message name.
+ *
+ * Remember that "sizeof" doesn't count the 'rest' field in our message
+ * structure.
+ */
+#define KBUS_ENTIRE_MSG_LEN(name_len, data_len) \
+ (sizeof(struct kbus_entire_message) + \
+ KBUS_PADDED_NAME_LEN(name_len) + \
+ KBUS_PADDED_DATA_LEN(data_len) + 4)
+
+/*
+ * The message name starts at entire->rest[0].
+ * The message data starts after the message name - given the message
+ * name's length (in bytes), that is at index:
+ */
+#define KBUS_ENTIRE_MSG_DATA_INDEX(name_len) ((name_len+1+3)/4)
+/*
+ * Given the message name length (in bytes) and the message data length (also
+ * in bytes), the index of the entire message end guard is thus:
+ */
+#define KBUS_ENTIRE_MSG_END_GUARD_INDEX(name_len, data_len) \
+ ((name_len+1+3)/4 + (data_len+3)/4)
+
+/*
+ * Find a pointer to the message's name.
+ *
+ * It's either the given name pointer, or just after the header (if the pointer
+ * is NULL)
+ */
+static inline char *kbus_msg_name_ptr(const struct kbus_message_header
+ *hdr)
+{
+ if (hdr->name) {
+ return hdr->name;
+ } else {
+ struct kbus_entire_message *entire;
+ entire = (struct kbus_entire_message *)hdr;
+ return (char *)&entire->rest[0];
+ }
+}
+
+/*
+ * Find a pointer to the message's data.
+ *
+ * It's either the given data pointer, or just after the name (if the pointer
+ * is NULL)
+ */
+static inline void *kbus_msg_data_ptr(const struct kbus_message_header
+ *hdr)
+{
+ if (hdr->data) {
+ return hdr->data;
+ } else {
+ struct kbus_entire_message *entire;
+ __u32 data_idx;
+
+ entire = (struct kbus_entire_message *)hdr;
+ data_idx = KBUS_ENTIRE_MSG_DATA_INDEX(hdr->name_len);
+ return (void *)&entire->rest[data_idx];
+ }
+}
+
+/*
+ * Find a pointer to the message's (second/final) end guard.
+ */
+static inline __u32 *kbus_msg_end_ptr(struct kbus_entire_message
+ *entire)
+{
+ __u32 end_guard_idx =
+ KBUS_ENTIRE_MSG_END_GUARD_INDEX(entire->header.name_len,
+ entire->header.data_len);
+ return (__u32 *) &entire->rest[end_guard_idx];
+}
+
+/*
+ * Things KBUS changes in a message
+ * --------------------------------
+ * In general, KBUS leaves the content of a message alone. However, it does
+ * change:
+ *
+ * - the message id (if id.network_id is unset - it assigns a new serial
+ * number unique to this message)
+ * - the from id (if from.network_id is unset - it sets the local_id to
+ * indicate the Ksock this message was sent from)
+ * - the KBUS_BIT_WANT_YOU_TO_REPLY bit in the flags (set or cleared
+ * as appropriate)
+ * - the SYNTHETIC bit, which KBUS will always unset in a user message
+ */
+
+/*
+ * Flags for the message 'flags' word
+ * ----------------------------------
+ * The KBUS_BIT_WANT_A_REPLY bit is set by the sender to indicate that a
+ * reply is wanted. This makes the message into a request.
+ *
+ * Note that setting the WANT_A_REPLY bit (i.e., a request) and
+ * setting 'in_reply_to' (i.e., a reply) is bound to lead to
+ * confusion, and the results are undefined (i.e., don't do it).
+ *
+ * The KBUS_BIT_WANT_YOU_TO_REPLY bit is set by KBUS on a particular message
+ * to indicate that the particular recipient is responsible for replying
+ * to (this instance of the) message. Otherwise, KBUS clears it.
+ *
+ * The KBUS_BIT_SYNTHETIC bit is set by KBUS when it generates a synthetic
+ * message (an exception, if you will), for instance when a replier has
+ * gone away and therefore a reply will never be generated for a request
+ * that has already been queued.
+ *
+ * Note that KBUS does not check that a sender has not set this
+ * on a message, but doing so may lead to confusion.
+ *
+ * The KBUS_BIT_URGENT bit is set by the sender if this message is to be
+ * treated as urgent - i.e., it should be added to the *front* of the
+ * recipient's message queue, not the back.
+ *
+ * Send flags
+ * ==========
+ * There are two "send" flags, KBUS_BIT_ALL_OR_WAIT and KBUS_BIT_ALL_OR_FAIL.
+ * Either one may be set, or both may be unset.
+ *
+ * If both bits are set, the message will be rejected as invalid.
+ *
+ * Both flags are ignored in reply messages (i.e., messages with the
+ * 'in_reply_to' field set).
+ *
+ * If both are unset, then a send will behave in the default manner. That is,
+ * the message will be added to a listener's queue if there is room but
+ * otherwise the listener will (silently) not receive the message.
+ *
+ * (Obviously, if the listener is a replier, and the message is a request,
+ * then a KBUS message will be synthesised in the normal manner when a
+ * request is lost.)
+ *
+ * If the KBUS_BIT_ALL_OR_WAIT bit is set, then a send should block until
+ * all recipients can be sent the message. Specifically, before the message is
+ * sent, all recipients must have room on their message queues for this
+ * message, and if they do not, the send will block until there is room for the
+ * message on all the queues.
+ *
+ * If the KBUS_BIT_ALL_OR_FAIL bit is set, then a send should fail if all
+ * recipients cannot be sent the message. Specifically, before the message is
+ * sent, all recipients must have room on their message queues for this
+ * message, and if they do not, the send will fail.
+ */
+
+/*
+ * When a $.KBUS.ReplierBindEvent message is constructed, we use the
+ * following to encapsulate its data.
+ *
+ * This indicates whether it is a bind or unbind event, who is doing the
+ * bind or unbind, and for what message name. The message name is padded
+ * out to a multiple of four bytes, allowing for a terminating null byte,
+ * but the name length is the length without said padding (so, in C terms,
+ * strlen(name)).
+ *
+ * As for the message header data structure, the actual data "goes off the end"
+ * of the datastructure.
+ */
+struct kbus_replier_bind_event_data {
+ __u32 is_bind; /* 1=bind, 0=unbind */
+ __u32 binder; /* Ksock id of binder */
+ __u32 name_len; /* Length of name */
+ __u32 rest[]; /* Message name */
+};
+
+#if !__KERNEL__
+#define BIT(num) (((unsigned)1) << (num))
+#endif
+
+#define KBUS_BIT_WANT_A_REPLY BIT(0)
+#define KBUS_BIT_WANT_YOU_TO_REPLY BIT(1)
+#define KBUS_BIT_SYNTHETIC BIT(2)
+#define KBUS_BIT_URGENT BIT(3)
+
+#define KBUS_BIT_ALL_OR_WAIT BIT(8)
+#define KBUS_BIT_ALL_OR_FAIL BIT(9)
+
+/*
+ * Standard message names
+ * ======================
+ * KBUS itself has some predefined message names.
+ *
+ * Synthetic Replies with no data
+ * ------------------------------
+ * These are sent to the original Sender of a Request when KBUS knows that the
+ * Replier is not going to Reply. In all cases, you can identify which message
+ * they concern by looking at the "in_reply_to" field:
+ *
+ * * Replier.GoneAway - the Replier has gone away before reading the Request.
+ * * Replier.Ignored - the Replier has gone away after reading a Request, but
+ * before replying to it.
+ * * Replier.Unbound - the Replier has unbound (as Replier) from the message
+ * name, and is thus not going to reply to this Request in its unread message
+ * queue.
+ * * Replier.Disappeared - the Replier has disappeared when an attempt is made
+ * to send a Request whilst polling (i.e., after EAGAIN was returned from an
+ * earlier attempt to send a message). This typically means that the Ksock
+ * bound as Replier closed.
+ * * ErrorSending - an unexpected error occurred when trying to send a Request
+ * to its Replier whilst polling.
+ *
+ * Synthetic Announcements with no data
+ * ------------------------------------
+ * * UnbindEventsLost - sent (instead of a Replier Bind Event) when the unbind
+ * events "set aside" list has filled up, and thus unbind events have been
+ * lost.
+ */
+#define KBUS_MSG_NAME_REPLIER_GONEAWAY "$.KBUS.Replier.GoneAway"
+#define KBUS_MSG_NAME_REPLIER_IGNORED "$.KBUS.Replier.Ignored"
+#define KBUS_MSG_NAME_REPLIER_UNBOUND "$.KBUS.Replier.Unbound"
+#define KBUS_MSG_NAME_REPLIER_DISAPPEARED "$.KBUS.Replier.Disappeared"
+#define KBUS_MSG_NAME_ERROR_SENDING "$.KBUS.ErrorSending"
+#define KBUS_MSG_NAME_UNBIND_EVENTS_LOST "$.KBUS.UnbindEventsLost"
+
+/*
+ * Replier Bind Event
+ * ------------------
+ * This is the only message name for which KBUS generates data -- see
+ * kbus_replier_bind_event_data. It is also the only message name which KBUS
+ * does not allow binding to as a Replier.
+ *
+ * This is the message that is sent when a Replier binds or unbinds to another
+ * message name, if the KBUS_IOC_REPORTREPLIERBINDS ioctl has been used to
+ * request such notification.
+ */
+#define KBUS_MSG_NAME_REPLIER_BIND_EVENT "$.KBUS.ReplierBindEvent"
+
+#define KBUS_IOC_MAGIC 'k' /* 0x6b - which seems fair enough for now */
+/*
+ * RESET: reserved for future use
+ */
+#define KBUS_IOC_RESET _IO(KBUS_IOC_MAGIC, 1)
+/*
+ * BIND - bind a Ksock to a message name
+ * arg: struct kbus_bind_request, indicating what to bind to
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_BIND _IOW(KBUS_IOC_MAGIC, 2, char *)
+/*
+ * UNBIND - unbind a Ksock from a message id
+ * arg: struct kbus_bind_request, indicating what to unbind from
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_UNBIND _IOW(KBUS_IOC_MAGIC, 3, char *)
+/*
+ * KSOCKID - determine a Ksock's Ksock id
+ *
+ * The network_id for the current Ksock is, by definition, 0, so we don't need
+ * to return it.
+ *
+ * arg (out): __u32, indicating this Ksock's local_id
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_KSOCKID _IOR(KBUS_IOC_MAGIC, 4, char *)
+/*
+ * REPLIER - determine the Ksock id of the replier for a message name
+ * arg: struct kbus_bind_query
+ *
+ * - on input, specify the message name to ask about.
+ * - on output, KBUS fills in the relevant Ksock id in the return_value,
+ * or 0 if there is no bound replier
+ *
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_REPLIER _IOWR(KBUS_IOC_MAGIC, 5, char *)
+/*
+ * NEXTMSG - pop the next message from the read queue
+ * arg (out): __u32, number of bytes in the next message, 0 if there is no
+ * next message
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_NEXTMSG _IOR(KBUS_IOC_MAGIC, 6, char *)
+/*
+ * LENLEFT - determine how many bytes are left to read of the current message
+ * arg (out): __u32, number of bytes left, 0 if there is no current read
+ * message
+ * retval: 1 if there was a message, 0 if there wasn't, negative for failure
+ */
+#define KBUS_IOC_LENLEFT _IOR(KBUS_IOC_MAGIC, 7, char *)
+/*
+ * SEND - send the current message
+ * arg (out): struct kbus_msg_id, the message id of the sent message
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_SEND _IOR(KBUS_IOC_MAGIC, 8, char *)
+/*
+ * DISCARD - discard the message currently being written (if any)
+ * arg: none
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_DISCARD _IO(KBUS_IOC_MAGIC, 9)
+/*
+ * LASTSENT - determine the message id of the last message SENT
+ * arg (out): struct kbus_msg_id, {0,0} if there was no last message
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_LASTSENT _IOR(KBUS_IOC_MAGIC, 10, char *)
+/*
+ * MAXMSGS - set the maximum number of messages on a Ksock read queue
+ * arg (in): __u32, the requested length of the read queue, or 0 to just
+ * request how many there are
+ * arg (out): __u32, the length of the read queue after this call has
+ * succeeded
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_MAXMSGS _IOWR(KBUS_IOC_MAGIC, 11, char *)
+/*
+ * NUMMSGS - determine how many messages are in the read queue for this Ksock
+ * arg (out): __u32, the number of messages in the read queue.
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_NUMMSGS _IOR(KBUS_IOC_MAGIC, 12, char *)
+/*
+ * UNREPLIEDTO - determine the number of requests (marked "WANT_YOU_TO_REPLY")
+ * which we still need to reply to.
+ * arg(out): __u32, said number
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_UNREPLIEDTO _IOR(KBUS_IOC_MAGIC, 13, char *)
+/*
+ * MSGONLYONCE - should we receive a message only once?
+ *
+ * This IOCTL tells a Ksock whether it should only receive a particular message
+ * once, even if it is both a Replier and Listener for the message (in which
+ * case it will always get the message as Replier, if appropriate), or if it is
+ * registered as multiple Listeners for the message.
+ *
+ * arg(in): __u32, 1 to change to "only once", 0 to change to the default,
+ * 0xFFFFFFFF to just return the current/previous state.
+ * arg(out): __u32, the previous state.
+ * retval: 0 for success, negative for failure (-EINVAL if arg in was not one
+ * of the specified values)
+ */
+#define KBUS_IOC_MSGONLYONCE _IOWR(KBUS_IOC_MAGIC, 14, char *)
+/*
+ * VERBOSE - should KBUS output verbose "printk" messages (for this device)?
+ *
+ * This IOCTL tells a Ksock whether it should output debugging messages. It is
+ * only effective if the kernel module has been built with the VERBOSE_DEBUGGING
+ * flag set.
+ *
+ * arg(in): __u32, 1 to change to "verbose", 0 to change to "quiet",
+ * 0xFFFFFFFF to just return the current/previous state.
+ * arg(out): __u32, the previous state.
+ * retval: 0 for success, negative for failure (-EINVAL if arg in was not one
+ * of the specified values)
+ */
+#define KBUS_IOC_VERBOSE _IOWR(KBUS_IOC_MAGIC, 15, char *)
+
+/*
+ * NEWDEVICE - request another KBUS device (/dev/kbus<n>).
+ *
+ * The next device number (up to a maximum of 255) will be allocated.
+ *
+ * arg(out): __u32, the new device number (<n>)
+ * retval: 0 for success, negative for failure
+ */
+#define KBUS_IOC_NEWDEVICE _IOR(KBUS_IOC_MAGIC, 16, char *)
+
+/*
+ * REPORTREPLIERBINDS - request synthetic messages announcing Replier
+ * bind/unbind events.
+ *
+ * If this flag is set, then when someone binds or unbinds to a message name as
+ * a Replier, KBUS will send out a synthetic Announcement of this fact.
+ *
+ * arg(in): __u32, 1 to change to "report", 0 to change to "do not report",
+ * 0xFFFFFFFF to just return the current/previous state.
+ * arg(out): __u32, the previous state.
+ * retval: 0 for success, negative for failure (-EINVAL if arg in was not one
+ * of the specified values)
+ */
+#define KBUS_IOC_REPORTREPLIERBINDS _IOWR(KBUS_IOC_MAGIC, 17, char *)
+
+/* If adding another IOCTL, remember to increment the next number! */
+#define KBUS_IOC_MAXNR 17
+
+#if !__KERNEL__ && defined(__cplusplus)
+}
+#endif
+
+#endif /* _kbus_defns */
--
1.7.1
^ permalink raw reply related
* [PATCH 1/5] Documentation for KBUS
From: Tony Ibbs @ 2011-02-27 18:11 UTC (permalink / raw)
To: Linux-embedded; +Cc: Tibs at Kynesim, Richard Watts, Grant Likely
In-Reply-To: <cover.1298829754.git.tibs@tonyibbs.co.uk>
From: Tibs <tibs@tonyibbs.co.uk>
Signed-off-by: Tony Ibbs <tibs@tonyibbs.co.uk>
---
Documentation/Kbus.txt | 1222 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1222 insertions(+), 0 deletions(-)
create mode 100644 Documentation/Kbus.txt
diff --git a/Documentation/Kbus.txt b/Documentation/Kbus.txt
new file mode 100644
index 0000000..7cf723f
--- /dev/null
+++ b/Documentation/Kbus.txt
@@ -0,0 +1,1222 @@
+=============================================
+KBUS -- Lightweight kernel-mediated messaging
+=============================================
+
+Summary
+=======
+KBUS provides lightweight kernel-mediated messaging for Linux.
+
+* "lightweight" means that there is no intent to provide complex or
+ sophisticated mechanisms - if you need something more, consider DBUS or
+ other alternatives.
+
+* "kernel-mediated" means that the actual business of message passing and
+ message synchronisation is handled by a kernel module.
+
+* "for Linux" means what it says, since the Linux kernel is required.
+
+Initial use is expected to be in embedded systems.
+
+There is (at least initially) no intent to aim for a "fast" system - this is
+not aimed at real-time systems.
+
+Although the implementation is kernel-mediated, there is a mechanism
+("Limpets") for commnicating KBUS messages between buses and/or systems.
+
+Intentions
+==========
+KBUS is intended:
+
+* To be simple to use and simple to understand.
+* To have a small codebase, written in C.
+* To provide predictable message delivery.
+* To give deterministic message ordering.
+* To guarantee a reply to every request.
+
+It needs to be simple to use and understand because the expected users are
+typically busy with other matters, and do not have time to spend learning
+a complex messaging system.
+
+It needs to have a small codebase, written in C, because embedded systems
+often lack resources, and may not have enough space for C++ libraries, or
+messaging systems supporting more complex protocol stacks.
+
+Our own experience on embedded systems of various sizes indicates that
+the last three points are especially important.
+
+Predictable message delivery means the user can know whether they can tell in
+what circumstances messages will or will not be received.
+
+Deterministic message ordering means that all recipients of a given set of
+messages will receive them in the same order as all other recpients (and this
+will be the order in which the messages were sent). This is important when
+several part of (for instance) an audio/video stack are interoperating.
+
+Guaranteeing that a request will always result in a reply means that the user
+will be told if the intended replier has (for instance) crashed. This again
+allows for simpler use of the system.
+
+The basics
+==========
+Python and C
+------------
+Although the KBUS kernel module is written in C, the module tests are written
+in Python, and there is a Python module providing useful interfaces, which is
+expected to be the normal way of using KBUS from Python.
+
+There is also a C library (libkbus) which provides a similar level of
+abstraction, so that C programmers can use KBUS without having to handle the
+low level details of sockets and message datastructures. Note that the C
+programer using KBUS does need to have some awareness of how KBUS messages
+work in order to get memory management right.
+
+Messages
+========
+Message names
+-------------
+All messages have names - for instance "$.Sensors.Kitchen".
+
+All message names start with "$.", followed by one or more alphanumeric words
+separated by dots. There are two wildcard characters, "*" and "%", which can
+be the last word of a name.
+
+Thus (in some notation or other)::
+
+ name := '$.' [ word '.' ]+ ( word | '*' | '%' )
+ word := alphanumerics
+
+Case is significant. There is probably a limit on the maximum size of a
+subname, and also on the maximum length of a message name.
+
+Names form a name hierarchy or tree - so "$.Sensors" might have children
+"$.Sensors.Kitchen" and "$.Sensors.Bedroom".
+
+If the last word of a name is "*", then this is a wildcard name that also
+includes all the child names at that level and below -- i.e., all the names
+that start with the name up to the "*". So "$.Sensors.*" includes
+"$.Sensors.Kitchen", "$.Sensors.Bedroom", "$.Sensors.Kitchen.FireAlarm",
+"$.Sensors.Kitchen.Toaster", "$.Sensors.Bedroom.FireAlarm", and so on.
+
+If the last word of a name is "%", then this is a wildcard name that also
+includes all the child names at that level -- i.e., all the names obtained by
+replacing the "%" by another word. So "$.Sensors.%" includes
+"$.Sensors.Kitchen" and "$.Sensors.Bedroom", but not
+"$.Sensors.Kitchen.Toaster".
+
+Message ids
+-----------
+Every message is expected to have a unique id.
+
+A message id is made up of two parts, a network id and a serial number.
+
+The network id is used to carry useful information when a message is
+transferred from one KBUS system to another (for instance, over a bridge). By
+default (for local messages) it is 0.
+
+A serial number is used to identify the particular message within a network.
+
+If a message is sent via KBUS with a network id of 0, then KBUS itself will
+assign a new message id to the message, with the network id (still) 0, and
+with the serial number one more than the last serial number assigned. Thus for
+local messages, message ids ascend, and their order is deterministic.
+
+If a message is sent via KBUS with a non-zero network id, then KBUS does not
+touch its message id.
+
+Network ids are represented textually as ``{n,s}``, where ``n`` is the
+network id and ``s`` is the serial number.
+
+ Message id {0,0} is reserved for use as an invalid message id. Both
+ network id and serial number are unsigned 32-bit integers. Note that this
+ means that local serial numbers will eventually wrap.
+
+Message content
+---------------
+Messages are made of the following parts:
+
+:start and end guards:
+
+ These are unsigned 32-bit words. 'start_guard' is notionally "Kbus",
+ and 'end_guard' (the 32 bit word after the rest of the message) is
+ notionally "subK". Obviously that depends on how one looks at the 32-bit
+ word. Every message shall start with a start guard and end with an end
+ guard (but see `Message implementation`_ for details).
+
+ These provide some help in checking that a message is well formed, and in
+ particular the end guard helps to check for broken length fields.
+
+ If the message layout changes in an incompatible manner (this has happened
+ once, and is strongly discouraged), then the start and end guards change.
+
+Unset
+~~~~~
+Unset values are 0, or have zero length (as appropriate).
+
+It is not possible for a message name to be unset.
+
+The message header
+~~~~~~~~~~~~~~~~~~
+:message id: identifies this particular message. This is made up of a network
+ id and a serial number, and is discussed in `Message ids`_.
+
+ When replying to a message, copy this value into the 'In reply to' field.
+
+:in_reply_to: is the message id of the message that this is a reply to.
+
+ This shall be set to 0 unless this message *is* a reply to a previous
+ message. In other words, if this value is non-0, then the message *is* a
+ reply.
+
+:to: is the Ksock id identifying who the message is to be sent to.
+
+ When writing a new message, this should normally be set to 0, meaning
+ "anyone listening" (but see below if "state" is being maintained).
+
+ When replying to a message, it shall be set to the 'from' value of the
+ orginal message.
+
+ When constructing a request message (a message wanting a reply), then it can
+ be set to a specific replier's Ksock id. When such a message is sent, if the
+ replier bound (at that time) does not have that specific Ksock id, then the
+ send will fail.
+
+:from: indicates the Ksock id of the message's sender.
+
+ When writing a new message, set this to 0, since KBUS will set it.
+
+ When reading a message, this will have been set by KBUS.
+
+:orig_from: this indicates the original sender of a message, when being
+ transported via Limpet. This will be documented in more detail in the future.
+
+:final_to: this indicates the final target of a message, when being
+ transported via Limpet. This will be documented in more detail in the future.
+
+:extra: this is a zero field, for future expansion. KBUS will always set this
+ field to zero.
+
+:flags: indicates extra information about the message. See `Message Flags`_
+ for detailed information.
+
+ When writing a message, typical uses include:
+
+ * the message is URGENT
+ * a reply is wanted
+
+ When reading a message, typical uses include:
+
+ * the message is URGENT
+ * a reply is wanted
+ * a reply is wanted from the specific reader
+
+ The top 16 bits of the flags field is reserved for use by the user - KBUS
+ will not touch it.
+
+:name_length: is the length of the message name in bytes. This will always be
+ non-zero, as a message name must always be given.
+
+:data_length: is the length of the message data in bytes. It may be zero
+ if there is no data associated with this message.
+
+:name: identifies the message. It must be terminated with a
+ zero byte (as is normal for C - in the Python binding a normal Python string
+ can be used, and the this will be done for you). Byte ordering is according
+ to that of the platform.
+
+ In an "entire" message (see `Message implementation`_ below) the name shall
+ be padded out to a multiple of 4 bytes. Neither the terminating zero byte
+ nor the padding are included in the name length. Padding should be with
+ zero bytes.
+
+:data: is optional. KBUS does not touch the content of the
+ data, but just copies it. Byte ordering is according to that of the
+ platform.
+
+ In an "entire" message (see `Message implementation`_ below) the data shall,
+ if present, be padded out to a multiple of 4 bytes. This padding is not
+ included in the data length, and the padding bytes may be whatever byte
+ values are convenient to the user. KBUS does not guarantee to copy the exact
+ given padding bytes (in fact, current implementations just ignore them).
+
+Message implementation
+~~~~~~~~~~~~~~~~~~~~~~
+There are two ways in which a message may be constructed, "pointy" and
+"entire".
+See the ``kbus_defns.h`` header file for details.
+
+.. note:: The Python binding hides most of the detail of the message
+ implementation from the user, so if you are using Python you may be able to
+ skip this section.
+
+In a "pointy" message, the ``name`` and ``data`` fields in the message header
+are C pointers to the actual name and data. If there is no data, then the
+``data`` field is NULL. This is probably the simplest form of message for a C
+programmer to create. This might be represented as::
+
+ start_guard: 'Kbus'
+ id: (0,0)
+ in_reply_to: (0,0)
+ to: 0
+ from: 0
+ name_len: 6
+ data_len: 0
+ name: ---------------------------> "$.Fred"
+ data: NULL
+ end_guard: 'subK'
+
+or (with data)::
+
+ start_guard: 'Kbus'
+ id: (0,0)
+ in_reply_to: (0,0)
+ to: 0
+ from: 0
+ name_len: 6
+ data_len: 7
+ name: ---------------------------> "$.Fred"
+ data: ---------------------------> "abc1234"
+ end_guard: 'subK'
+
+.. warning:: When writing a "pointy" message in C, be very careful not to
+ free the name and data between the ``write`` and the SEND, as it is
+ only when the message is sent that KBUS actually follows the ``name`` and
+ ``data`` pointers.
+
+ *After* the SEND, KBUS will have taken its own copies of the name and
+ (any) data.
+
+In an "entire" message, both ``name`` and ``data`` fields are required to be
+NULL. The message header is followed by the message name (padded as described
+above), any message data (also padded), and another end guard. This might be
+represented as::
+
+ start_guard: 'Kbus'
+ id: (0,0)
+ in_reply_to: (0,0)
+ to: 0
+ from: 0
+ name_len: 6
+ data_len: 0
+ name: NULL
+ data: NULL
+ end_guard: 'subK'
+ name_data: '$.Fred\x0\x0'
+ end_guard: 'subK'
+
+or (again with data)::
+
+ start_guard: 'Kbus'
+ id: (0,0)
+ in_reply_to: (0,0)
+ to: 0
+ from: 0
+ name_len: 6
+ data_len: 7
+ name: NULL
+ data: NULL
+ end_guard: 'subK'
+ name_data: '$.Fred\x0\x0'
+ data_data: 'abc1234\x0'
+ end_guard: 'subK'
+
+Note that in these examples:
+
+1. The message name is padded out to 6 bytes of name, plus one of terminating
+ zero byte, plus another zero byte to make 8, but the message's ``name_len``
+ is still 6.
+2. When there is no data, there is no "data data" after the name data.
+3. When there is data, the data is presented after the name, and is padded out
+ to a multiple of 4 bytes (but without the necessity for a terminating zero
+ byte, so it is possible to have no pad bytes if the data length is already
+ a multiple of 4). Again, the ``data_len`` always reflects the "real" data
+ length.
+4. Although the data shown is presented as ASCII strings for these examples,
+ it really is just bytes, with no assumption of its content/meaning.
+
+When writing/sending messages, either form may be used (again, the "pointy"
+form may be simpler for C programmers).
+
+When reading messages, however, the "entire" form is always returned - this
+removes questions about needing to free multiple returned datastructures (for
+instance, what to do if the user were to ask for the NEXTMSG, read a few
+bytes, and then DISCARD the rest).
+
+Limits
+~~~~~~
+Message names may not be shorter than 3 characters (since they must be at
+least "$." plus another character). An arbitrary limit is also placed on the
+maximum message length - this is currently 1000 characters, but may be
+reviewed in the future.
+
+Message data may, of course, be of zero length.
+
+When reading a message, an "entire" message is always returned.
+
+ .. note:: When using C to work with KBUS messages, it is generally
+ ill-advised to reference the message name and data "directly"::
+
+ char *name = msg->name;
+ uint8_t *data = msg->data;
+
+ since this will work for "pointy" messages, but not for "entire"
+ messages (where the ``name`` field will be NULL). Instead, it
+ is always better to do::
+
+ char *name = kbus_msg_name_ptr(msg);
+ uint8_t *data = kbus_msg_data_ptr(msg);
+
+ regardless of the message type.
+
+Message flags
+-------------
+KBUS reserves the bottom 16 bits of the flags word for predefined purposes
+(although not all of those bits are yet used), and guarantees not to touch the
+top 16 bits, which are available for use by the programmer as a particular
+application may wish.
+
+The WANT_A_REPLY bit is set by the sender to indicate that a
+reply is wanted. This makes the message into a request.
+
+ Note that setting the WANT_A_REPLY bit (i.e., a request) and
+ setting 'in_reply_to' (i.e., a reply) is bound to lead to
+ confusion, and the results are undefined (i.e., don't do it).
+
+The WANT_YOU_TO_REPLY bit is set by KBUS on a particular message
+to indicate that the particular recipient is responsible for replying
+to (this instance of the) message. Otherwise, KBUS clears it.
+
+The SYNTHETIC bit is set by KBUS when it generates a Status message, for
+instance when a replier has gone away and will therefore not be sending a
+reply to a request that has already been queued.
+
+ Note that KBUS does not check that a sender has not set this
+ flag on a message, but doing so may lead to confusion.
+
+The URGENT bit is set by the sender if this message is to be
+treated as urgent - i.e., it should be added to the *front* of the
+recipient's message queue, not the back.
+
+Send flags
+~~~~~~~~~~
+There are two "send" flags, ALL_OR_WAIT and ALL_OR_FAIL.
+Either one may be set, or both may be unset.
+
+ If both are set, the message will be rejected as invalid.
+
+ Both flags are ignored in reply messages (i.e., messages with the
+ 'in_reply_to' field set).
+
+If a message has ALL_OR_FAIL set, then a SEND will only succeed if the message
+could be added to all the (intended) recipient's message queues. Otherwise,
+SEND returns -EBUSY.
+
+If a message has ALL_OR_WAIT set, then a SEND will only succeed if the message
+could be added to all the (intended) recipient's message queues. Otherwise
+SEND returns -EAGAIN. In this case, the message is still being sent, and the
+caller should either call DISCARD (to drop it), or else use poll/select to
+wait for the send to finish. It will not be possible to call "write" until the
+send has completed or been discarded.
+
+These are primarily intended for use in debugging systems. In particular, note
+that the mechanisms dealing with ALL_OR_WAIT internally are unlikely to be
+very efficient.
+
+.. note:: The send flags will be less effective when messages are being
+ mediated via Limpets, as remote systems are involved.
+
+Things KBUS changes in a message
+--------------------------------
+In general, KBUS leaves the content of a message alone - mostly so that an
+individual KBUS module can "pass through" messages from another domain.
+However, it does change:
+
+- the message id's serial number (but only if its network id is unset)
+- the 'from' id (to indicate the Ksock this message was sent from)
+- the WANT_YOU_TO_REPLY bit in the flags (set or cleared as appropriate)
+- the SYNTHETIC bit, which will always be unset in a message sent by a
+ Sender
+
+KBUS will always set the 'extra' field to zero.
+
+Limpets will change:
+
+- the network id in any field that has one.
+- the 'orig_from' and 'final_to' fields (which in general should only be
+ manipulated by Limpets).
+
+Types of message
+================
+There are four basic message types:
+
+* Announcement -- a message aimed at any listeners, expecting no reply
+* Request -- a message aimed at a replier, who is expected to reply
+* Reply -- a reply to a request
+* Status -- a message generated by KBUS
+
+The Python interface provides a Message base class, and subclasses thereof for
+each of the "user" message types (but not currently for Status).
+
+Announcements
+-------------
+An announcement is the "plain" message type. It is a message that is being
+sent for all bound listeners to "hear".
+
+When creating a new announcement message, it has:
+
+ :message id: see `Message ids`_
+ :in reply to: unset (it's not a reply)
+ :to: unset (all announcements are broadcast to any listeners)
+ :from: unset (KBUS will set it)
+ :flags: typically unset, see `Message flags`_
+ :message name: as appropriate
+ :message data: as appropriate
+
+The Python interface provides an ``Announcement`` class to help in creating an
+announcement message.
+
+Request message
+---------------
+A request message is a message that wants a reply.
+
+Since only one Ksock may bind as a replier for a given message name, a
+request message wants a reply from a single Ksock. By default, this is
+whichever Ksock has bound to the message name at the moment of sending, but
+see `Stateful transactions`_.
+
+When creating a new request message, it has:
+
+ :message id: see `Message ids`_
+ :in reply to: unset (it's not a reply)
+ :to: either unset, or a specific Ksock id if the request
+ should fail if that Ksock is (no longer) the replier
+ for this message name
+ :from: unset (KBUS will set it)
+ :flags: the "needs a reply" flag should be set.
+ KBUS will set the "you need to reply" flag in the
+ copy of the message delivered to its replier.
+ :message name: as appropriate
+ :message data: as appropriate
+
+When receiving a request message, the WANT_YOU_TO_REPLY flag will be set if it
+is this recipient's responsibility to reply.
+
+The Python interface provides a ``Request`` class to help in creating a
+request message.
+
+When a request message is sent, it is an error if there is no replier bound to
+that message name.
+
+The message will, as normal, be delivered to all listeners, and will have the
+"needs a reply" flag set wherever it is received. However, only the copy of
+the message received by the replier will be marked with the WANT_YOU_TO_REPLY
+flag.
+
+ So, if a particular file descriptor is bound as listener and replier
+ for '$.Fred', it will receive two copies of the original message (one
+ marked as needing reply from that file descriptor). However, when the
+ reply is sent, only the "plain" listener will receive a copy of the reply
+ message.
+
+Reply message
+-------------
+A reply message is the expected response after reading a request message.
+
+A reply message is distinguished by having a non-zero 'in reply to' value.
+
+Each reply message is in response to a specific request, as indicated by the
+'in reply to' field in the message.
+
+The replier is helped to remember that it needs to reply to a request, because
+the request has the WANT_YOU_TO_REPLY flag set.
+
+When a reply is sent, all listeners for that message name will receive it.
+However, the original replier will not.
+
+When creating a new reply message, it has:
+
+ :message id: see `Message ids`_
+ :in reply to: the request message's 'message id'
+ :to: the request message's 'from' id
+ :from: unset (KBUS will set it)
+ :flags: typically unset, see `Message flags`_
+ :message name: the request message's 'message name'
+ :message data: as appropriate
+
+The Python interface provides a ``Reply`` class to help in creating a reply
+message, but more usefully there is also a ``reply_to`` function that creates
+a Reply Message from the original Request.
+
+Status message
+--------------
+KBUS generates Status messages (also sometimes referred to as "synthetic"
+messages) when a request message has been successfully sent, but the replier
+is unable to reply (for instance, because it has closed its Ksock). KBUS thus
+uses a Status message to provide the "reply" that it guarantees the sender
+will get.
+
+As you might expect, a KBUS status message is thus (technically) a reply
+message.
+
+A status message looks like:
+
+ :message id: as normal
+ :in reply to: the 'message id' of the message whose sending or
+ processing caused this message.
+ :to: the Ksock id of the recipient of the message
+ :from: the Ksock id of the sender of the message - this will
+ be 0 if the sender is KBUS itself (which is assumed for
+ most exceptions)
+ :flags: typically unset, see `Message flags`_
+ :message name: for KBUS exceptions, a message name in '$.KBUS.*'
+ :message data: for KBUS exceptions, normally absent
+
+KBUS status messages always have '$.KBUS.<something>' names (this may be a
+multi-level <something>), and are always in response to a previous message, so
+always have an 'in reply to'.
+
+Requests and Replies
+--------------------
+KBUS guarantees that each Request will (eventually) be matched by a consequent
+Reply (or Status [1]_) message, and only one such.
+
+The "normal" case is when the replier reads the request, and sends its own
+reply back.
+
+If a Request message has been successfully SENT, there are the following other
+cases to consider:
+
+1. The replier unbinds from that message name before reading the request
+ message from its queue. In this case, KBUS removes the message from the
+ repliers queue, and issues a "$.KBUS.Replier.Unbound" message.
+
+2. The replier closes itself (close the Ksock), but has not yet read the
+ message. In this case, KBUS issues a "$.KBUS.Replier.GoneAway" message.
+
+3. The replier closes itself (closes the Ksock), has read the message, but has
+ not yet (and now cannot) replied to it. In this case, KBUS issues a
+ "$.KBUS.Replier.Ignored" message.
+
+4. SEND did not complete, and the replier closes itself before the message can
+ be added to its message queue (by the POLL mechanism). In this case, KBUS
+ issues a "$.KBUS.Replier.Disappeared" message.
+
+5. SEND did not complete, and an error occurs when the POLL mechanims tries to
+ send the message. In this case, KBUS issues a "$.KBUS.ErrorSending"
+ message.
+
+In all these cases, the 'in_reply_to' field is set to the original request's
+message id. In the first three cases, the 'from' field will be set to the
+Ksock id of the (originally intended) replier. In the last two cases, that
+information is not available, and a 'from' of 0 (indicating KBUS itself) is
+used.
+
+.. [1] Remember that a Status message is essentially a specialisation of a
+ Reply message.
+
+.. note:: Limpets introduce some extra messages, which will be documented when
+ the proper Limpet documentation is written.
+
+KBUS end points - Ksocks
+========================
+The KBUS devices
+----------------
+Message interactions happen via the KBUS devices. Installing the KBUS kernel
+module always creates ``/dev/kbus0``, it may also create ``/dev/kbus1``, and
+so on.
+
+ The number of devices to create is indicated by an argument at module
+ installation, for instance::
+
+ # insmod kbus.ko num_kbus_devices=10
+
+Messages are sent by writing to a KBUS device, and received by reading from
+the same device. A variety of useful ioctls are also provided. Each KBUS
+device is independent - messages cannot be sent from ``/dev/kbus0`` to
+``/dev/kbus1``, since there is no shared information.
+
+Ksocks
+------
+Specifically, messages are written to and read from KBUS device file
+descriptors. Each such is termed a *Ksock* - this is a simpler term than "file
+descriptor", and has some resonance with "socket".
+
+Each Ksock may be any (one or more) of:
+
+* a Sender (opening the device for read/write)
+* a Listener (only needing to open the device for read)
+* a Replier (opening the device for read/write)
+
+Every Ksock has an id. This is a 32-bit unsigned number assigned by KBUS when
+the device is opened. The value 0 is reserved for KBUS itself.
+
+ The terms "listener id", "sender id", "replier id", etc., thus all refer
+ to a Ksock id, depending on what it is being used for.
+
+Senders
+-------
+Message senders are called "senders". A sender should open a Ksock for read
+and write, as it may need to read replies and error/status messages.
+
+A message is sent by:
+
+1. Writing the message to the Ksock (using the standard ``write`` function)
+2. Calling the SEND ioctl on the Ksock, to actually send the message. This
+ returns (via its arguments) the message id of the message sent. It also
+ returns status information about the send
+
+ The status information is to be documented.
+
+The DISCARD ioctl can be used to "throw away" a partially written message,
+before SEND has been called on it.
+
+If there are no listeners (of any type) bound to that message name, then the
+message will be ignored.
+
+If the message is flagged as needing a reply, and there are no repliers bound
+to that message name, then an error message will be sent to the sender, by
+KBUS.
+
+It is not possible to send a message with a wildcard message name.
+
+ As a restriction this makes the life of the implementor and documentor
+ easier. I believe it would also be confusing if provided.
+
+The sender does not need to bind to any message names in order to receive
+error and status messages from KBUS.
+
+When a sender sends a Request, an internal note is made that it expects a
+corresponding Reply (or possible a Status message from KBUS if the Replier
+goes away or unbinds from that message name, before replying). A place for
+that Reply is reserved in the sender's message queue. If the message queue
+fills up (either with messages waiting to be read, or with reserved slots for
+Replies), then the sender will not be able to send another Request until there
+is room on the message queue again.
+
+ Hopefully, this can be resolved by the sender reading a message off its
+ queue. However, if there are no messages to be read, and the queue is all
+ reserved for replies, the only solution is for the sender to wait for a
+ replier to send it something that it can then read.
+
+.. note:: What order do we describe things in? Don't forget:
+
+ If the message being sent is a request, then the replier bound to that
+ message name will (presumably) write a reply to the request. Thus the normal
+ sequence for a request is likely to be:
+
+ 1. write the request message
+ 2. read the reply
+
+ The sender does *not* need to bind to anything in order to receive a reply to
+ a request it has sent.
+
+ Of course, if a sender binds to listen to the name it uses for its
+ request, then it will get a copy of the request as sent, and it will
+ also get (an extra) copy of the reply. But see `Receiving messages once
+ only`_.
+
+Listeners
+---------
+Message recipients are called "listeners".
+
+Listeners indicate that they want to receive particular messages, by using the
+BIND ioctl on a Ksock to specify the name of the message that is to be
+listened for. If the binding is to a wildcarded message name, then the
+listener will receive all messages with names that match the wildcard.
+
+An ordinary listener will receive all messages with that name (sent to the
+relevant Ksock). A listener may make more than one binding on the same Ksock
+(indeed, it is allowed to bind to the same name more than once).
+
+Messages are received by:
+
+1. Using the NEXTMSG ioctl to request the next message (this also returns the
+ messages length in bytes)
+2. Calling the standard ``read`` function to read the message data.
+
+If NEXTMSG is called again, the next message will be readied for reading,
+whether the previous message has been read (or partially read) or not.
+
+If a listener no longer wants to receive a particular message name, then they
+can unbind from it, using the UNBIND ioctl. The message name and flags used in
+an UNBIND must match those in the corresponding BIND. Any messages in the
+listener's message queue which match that unbinding will be removed from the
+queue (i.e., the listener will not actually receive them). This does *not*
+affect the message currently being read.
+
+ Note that this has implication for binding and unbinding wildcards,
+ which must also match.
+
+Closing the Ksock also unbinds all the message bindings made on it.
+It does not affect message bindings made on other Ksocks.
+
+Repliers
+--------
+Repliers are a special sort of listener.
+
+For each message name, there may be a single "replier". A replier binds to a
+message name in the same way as any other listener, but sets the "replier"
+flag. If someone else has already bound to the same Ksock as a replier for
+that message name, the request will fail.
+
+Repliers only receive Requests (messages that are marked as wanting a reply).
+
+A replier may (should? must?) reply to the request - this is done by sending
+a Reply message through the Ksock from which the Request was read.
+
+It is perfectly legitimate to bind to a message as both replier and listener,
+in which case two copies of the message will be read, once as replier, and
+once as (just) listener (but see `Receiving messages once only`_).
+
+
+When a request message is read by the appropriate replier, KBUS will mark
+*that particular message* with the "you must reply" flag. This will not be set
+on copies of that message read by any (non-replier) listeners.
+
+ So, in the case where a Ksock is bound as replier and listener for the
+ same message name, only one of the two copies of the message received will
+ be marked as "you must reply".
+
+If a replier binds to a wildcarded message name, then they are the *default*
+replier for any message names satisfying that wildcard. If another replier
+binds to a more specific message name (matching that wildcard),
+then the specific message name binding "wins" - the wildcard replier will no
+longer receive that message name.
+
+ In particular '$.Fred.Jim' is more specific than '$.Fred.%' which in turn
+ is more specific than '$.Fred.*'
+
+This means that if a wildcard replier wants to guarantee to see all the
+messages matching their wildcard, they also need to bind as a listener for the
+same wildcarded name.
+
+For example:
+
+ Assume message names are of the form '$.Sensors.<Room>' or
+ '$.Sensors.<Room>.<Measurement>'.
+
+ Replier 1 binds to '$.Sensors.*'. They will be the default replier for
+ all sensor requests.
+
+ Replier 2 binds to '$.Sensors.%'. They will take over as the default
+ replier for any room specific requests.
+
+ Replier 3 binds to '$.Sensors.Kitchen.Temperature'. They will take over as
+ the replier for the kitchen temperature.
+
+ So:
+
+ - A message named '$.Sensors.Kitchen.Temperature' will go to replier 3.
+ - A message named '$.Sensors.Kitchen' or '$.Sensors.LivingRoom' will go to
+ replier 2.
+ - A message named '$.Sensors.LivingRoom.Temperature' will go to replier 1.
+
+When a Replier is closed (technically, when its ``release`` function is
+called by the kernel) KBUS traverses its outstanding message queue, and for
+each Request that has not been answered, generates a Status message saying
+that the Replier has "GoneAway".
+
+Similarly, if a Replier unbinds from replying to a mesage, KBUS traverses its
+outstanding message queue, and for each Request that has not been answered, it
+generates a Status message saying that it has "Unbound" from being a replier
+for that message name. It also forgets the message, which it is now not going
+to reply to.
+
+Lastly, when a Replier is closed, if it has read any Requests (technically,
+called NEXTMSG to pop them from the message queue), but not actually replied
+to them, then KBUS will send an "Ignored" Status message for each such
+Request.
+
+More information
+================
+Stateful transactions
+---------------------
+It is possible to make stateful message transactions, by:
+
+1. sending a Request
+2. receiving the Reply, and noting the Ksock id of the replier
+3. sending another Request to that specific replier
+4. and so on
+
+Sending a request to a particular Ksock will fail if that Ksock is no longer
+bound as replier to the relevant message name. This allows a sender to
+guarantee that it is communicating with a particular instance of the replier
+for a message name.
+
+Queues filling up
+-----------------
+Messages are sent by a mechanism which:
+
+1. Checks the message is plausible (it has a plausible message name,
+ and the right sort of "shape")
+2. If the message is a Request, checks that the sender has room on its message
+ queue for the (eventual) Reply.
+3. Finds the Ksock ids of all the listeners and repliers bound to that
+ messages name
+4. Adds the message to the queue for each such listener/replier
+
+This can cause problems if one of the queues is already full (allowing
+infinite expansion of queues would also cause problems, of couse).
+
+If a *sender* attempts to send a Request, but does not have room on its
+message queue for the (corresponding) Reply, then the message will not be
+sent, and the send will fail. Note that the message id will not be set, and
+the blocking behaviours defined below do not occur.
+
+If a *replier* cannot receive a particular message, because its queue is full,
+then the message will not be sent, and the send will fail with an error. This
+does, however, set the message id (and thus the "last message id" on the
+sender).
+
+Moreover, a sender can indicate if it wants a message to be:
+
+1. Added to all the listener queues, regardless, in which case it will block
+ until that can be done (ALL_OR_WAIT, sender blocks)
+2. Added to all the listener queues, and fail if that can't be done
+ (ALL_OR_FAIL)
+3. Added to all the listener queues that have room (the default)
+
+See `Message flags`_ for more details.
+
+Urgent messages
+---------------
+Messages may be flagged urgent. In this case they will be added to the front
+of the destination message queue, rather than the end - in other words, they
+will be the next message to be "popped" by NEXTMSG.
+
+Note that this means that if two urgent messages are sent to the same target,
+and *then* a NEXTMSG/read occurs, the second urgent message will be popped and
+read first.
+
+Select, write/send and "next message", blocking
+-----------------------------------------------
+.. warning:: At the moment, ``read`` and ``write`` are always non-blocking.
+
+``read`` returns more of the currently selected message, or EOF if there is no
+more of that message to read (and thus also if there is no currently selected
+message). The NEXTMSG ioctl is used to select ("pop") the next message.
+
+``write`` writes to the end of the currently-being-written message. The
+DISCARD ioctl can be used to discard the data written so far, and the SEND
+ioctl to send the (presumably completed message). Whilst the message is being
+sent, it is not possible to use ``write``.
+
+Note that if SEND is used to send a Request, then KBUS ensures that there will
+always be either a Reply or a Status message in response to that request.
+
+Specifically, if:
+
+1. The Replier "goes away" (and its "release" function is called) before
+ reading the Request (specifically, before calling NEXTMSG to pop it from
+ the message queue)
+2. The Replier "goes away" (and its "release" function is called) before
+ replying to a Request that it has already read (i.e., used NEXTMSG to pop
+ from the message queue)
+3. The Replier unbinds from that Request message name before reading the
+ Request (with the same caveat on what that means)
+4. Select/poll attempts to send the Request, and discovers that the
+ Replier has disappeared since the initial SEND
+5. Select/poll attempts to send the Request, and some other error occurs
+
+then KBUS will "reply" with an appropriate Status message.
+
+--------------------------------------------------
+
+KBUS support its own particular variation on blocking of message sending.
+
+First of all, it supports use of "select" to determine if there are any
+messages waiting to be read. So, for instance (in Python)::
+
+ with Ksock(0,'rw') as sender:
+ with Ksock(0,'r') as listener:
+ (r,w,x) = select.select([listener],[],[],0)
+ assert r == []
+
+ listener.bind('$.Fred')
+ msg = Announcement('$.Fred','data')
+ sender.send_msg(msg)
+
+ (r,w,x) = select.select([listener],[],[],0)
+ assert r == [listener]
+
+This simply checks if there is a message in the Ksock's message list, waiting
+to be "popped" with NEXTMSG.
+
+Secondly, ``write``, SEND and DISCARD interact in what is hoped to be a
+sensible manner. Specifically:
+
+* When SEND (i.e., the SEND ioctl) is called, KBUS can either:
+
+ 1. Succeed in sending the message. The Ksock is now ready for ``write`` to
+ be called on it again.
+ 2. Failed in sending the message (possibly, if the message was a Request,
+ with EADDRNOTAVAIL, indicating that there is no Replier for that
+ Request). The Ksock is now ready for ``write`` to be called on it again.
+ 3. If the message was marked ALL_OR_WAIT, then it may fail with EAGAIN.
+ In this case, the Ksock is still in sending state, and an attempt to
+ call ``write`` will fail (with EALREADY). The caller can either use
+ DISCARD to discard the message, or use select/poll to wait for the
+ message to finish sending.
+
+Thus "select" for the write case checks whether it is allowed to call
+"write" - for instance::
+
+ with Ksock(0,'rw') as sender:
+ write_list = [sender]
+ with Ksock(0,'r') as listener1:
+ write_list= [sender,listener1]
+ read_list = [listener1]
+
+ (r,w,x) = select.select(read_list,write_list,[],0)
+ assert r == []
+ assert w == [sender]
+ assert x == []
+
+ with Ksock(0,'rw') as listener2:
+ write_list.append(listener2)
+ read_list.append(listener2)
+
+ (r,w,x) = select.select(read_list,write_list,[],0)
+ assert r == []
+ assert len(w) == 2
+ assert sender in w
+ assert listener2 in w
+ assert x == []
+
+Receiving messages once only
+----------------------------
+In normal usage (and by default), if a Ksock binds to a message name multiple
+times, it will receive multiple copies of a message. This can happen:
+
+* explicitly (the Ksock deliberately and explicitly binds to the same name
+ more than once, seeking this effect).
+* as a result of binding to a message name and a wildcard that includes the
+ same name, or two overlapping wildcards.
+* as a result of binding as Replier to a name, and also as Listener to the
+ same name (possibly via a wildcard). In this case, multiple copies will
+ only be received when a Request with that name is made.
+
+Several programmers have complained that the last case, in particular, is very
+inconvenient, and thus the "receive a message once only" facility has been
+added.
+
+Using the MSGONCEONLY IOCTL, it is possible to tell a Ksock that only one copy
+of a particular message should be received, even if multiple are "due". In the
+case of the Replier/Listener copies, it will always be the message to which
+the Replier should reply (the one with WANT_YOU_TO_REPLY set) that will be
+received.
+
+Please use this facility with care, and only if you really need it.
+
+IOCTLS
+------
+The KBUS ioctls are defined (with explanatory comments) in the kernel module
+header file (``kbus_defns.h``). They are:
+
+:RESET: Currently has no effect
+:BIND: Bind to a particular message name (possibly as replier).
+:UNBIND: Unbind from a binding - must match exactly.
+:KSOCKID: Determine the Ksock id of the Ksock used
+:REPLIER: Determine who is bound as replier to a particular message
+ name. This returns 0 or the Ksock id of the replier.
+:NEXTMSG: Pop the next message from the Ksock's message queue, ready
+ for reading (with ``read``), and return its length (in bytes).
+ If there is no next message, return a length of 0.
+ The length is always the length of an "entire" message (see
+ `Message implementation`_).
+:LENLEFT: Determine how many bytes of the message currently being read
+ are still to read.
+:SEND: Send the current outstanding message for this Ksock (i.e., the
+ bytes written to the Ksock since the last SEND or DISCARD).
+ Return the message id of the message, and maybe other status
+ information.
+:DISCARD: Discard (throw away) the current outstanding message for this
+ Ksock (i.e., any bytes written to the Ksock since the last
+ SEND or DISCARD).
+:LASTSENT: Determine the message id of the last message SENT on this
+ Ksock.
+:MAXMSGS: Set the maximum length of the (read) message queue for this
+ KSOCK, and return the actual length that is set. An attempt
+ to set the queue length to 0 will just return the current
+ queue length.
+:NUMMSGS: Determine how many messages are outstanding in this Ksock's
+ read queue.
+:UNREPLIEDTO: Determines how many Requests (marked "WANT_YOU_TO_REPLY")
+ this Ksock still needs to reply to. This is primarily a
+ development tool.
+:MSGONLYONCE: Determines whether only one copy of a message will be
+ received, even if the message name is bound to multiple times.
+ May also be used to query the current state.
+:VERBOSE: Determines whether verbose kernel messages should be output or
+ not. Affects the *device* (the entire Ksock).
+ May also be used to query the current state.
+:NEWDEVICE: Requests another KBUS device (``/dev/kbus/<n>``). The next
+ KBUS device number (up to a maximum of 255) will be allocated.
+ Returns the new device number.
+:REPORTREPLIERBINDS: Request synthetic messages announcing Replier BIND/UNBIND
+ events. These are messages named "$.KBUS.ReplierBindEvent",
+ and are the only predefined messages with data.
+ Both Python and C bindings provide a useful function to
+ extract the ``is_bind``, ``binder`` and ``name`` values from
+ the data.
+
+/proc/kbus/bindings
+-------------------
+``/proc/kbus/bindings`` is a debugging aid for reporting the listener id,
+exclusive flag and message name for each binding, for each kbus device.
+
+An example might be::
+
+ $ cat /proc/kbus/bindings
+ # <device> is bound to <Ksock-ID> in <process-PID> as <Replier|Listener> for <message-name>
+ 1: 1 22158 R $.Sensors.*
+ 1: 2 22158 R $.Sensors.Kitchen.Temperature
+ 1: 3 22158 L $.Sensors.*
+ 13: 4 22159 L $.Jim.*
+ 13: 1 22159 R $.Fred
+ 13: 1 22159 L $.Jim
+ 13: 14 23021 L $.Jim.*
+
+This describes two KBUS devices (``/dev/kbus1`` and ``/dev/kbus13``).
+
+The first has bindings on Ksock ids 1, 2 and 3, for the given message names. The
+"R" indicates a replier binding, the "L" indicates a listener (non-replier)
+binding.
+
+The second has bindings on Ksock ids 4, 1 and 14. The order of the bindings
+reported is *not* particularly significant.
+
+Note that there is no communication between the two devices, so Ksock id 1 on
+device 1 is not related to (and has no commonality with) Ksock id 1 on device
+13.
+
+/proc/kbus/stats
+----------------
+``/proc/kbus/stats`` is a debugging aid for reporting various statistics about
+the KBUS devices and the Ksocks open on them.
+
+An example might be::
+
+ $ cat /proc/kbus/stats
+ dev 0: next file 5 next msg 8 unsent unbindings 0
+ ksock 4 last msg 0:7 queue 1 of 100
+ read byte 0 of 0, wrote byte 52 (max 60), sending
+ outstanding requests 0 (size 16, max 0), unsent replies 0 (max 0)
+ ksock 3 last msg 0:5 queue 0 of 1
+ read byte 0 of 0, wrote byte 0 (max 0), not sending
+ outstanding requests 1 (size 16, max 0), unsent replies 0 (max 0)
+
+or::
+
+ $ cat /proc/kbus/stats
+ dev 0: next file 4 next msg 101 unsent unbindings 0
+ ksock 3 last msg 0:0 queue 100 of 100
+ read byte 0 of 0, wrote byte 0 (max 0), not sending
+ outstanding requests 0 (size 16, max 0), unsent replies 0 (max 0)
+ ksock 2 last msg 0:100 queue 0 of 100
+ read byte 0 of 0, wrote byte 0 (max 0), not sending
+ outstanding requests 100 (size 102, max 92), unsent replies 0 (max 0)
+
+
+Error numbers
+-------------
+The following error numbers get special use. In Python, they are all returned
+as values inside the IOError exception.
+
+ Since we're trying to fit into the normal Un*x convention that negative
+ values are error numbers, and since Un*x defines many of these for us,
+ it is natural to make use of the relevant definitions. However, this also
+ means that we are often using them in an unnatural sense. I've tried to
+ make the error numbers used bear at least a vague relationship to their
+ (mis)use in KBUS.
+
+:EADDRINUSE: On attempting to bind a message name as replier: There is
+ already a replier bound for this message
+:EADDRNOTAVAIL: On attempting to send a Request message: There is no replier
+ bound for this message's name.
+
+ On attempting to send a Reply message: The sender of the
+ original request (i.e., the Ksock mentioned as the ``to``
+ in the Reply) is no longer connected.
+:EALREADY: On attempting to write to a Ksock, when a previous send has
+ returned EAGAIN. Either DISCARD the message, or use
+ select/poll to wait for the send to complete, and write to be
+ allowed.
+:EBADMSG: On attempting to bind, unbind or send a message: The message
+ name is not valid. On sending, this can also be because the
+ message name is a wildcard.
+:EBUSY: On attempting to send, then:
+
+ 1. For a request, the replier's message queue is full.
+ 2. For any message, with ALL_OR_FAIL set, one of the
+ targetted listener/replier queues was full.
+
+:ECONNREFUSED: On attempting to send a Reply, the intended recipient (the
+ notional original sender of the Request) is not expecting
+ a Reply with that message id in its 'in_reply_to'. Or, in
+ other words, this appears to be an attempt to reply to the
+ wrong message id or the wrong Ksock.
+:EINVAL: Something went wrong (generic error).
+:EMSGSIZE: On attempting to write a message: Data was written after
+ the end of the message (i.e., after the final end guard
+ of the message).
+:ENAMETOOLONG: On attempting to bind, unbind or send a message: The message
+ name is too long.
+:ENOENT: On attempting to open a Ksock: There is no such device
+ (normally because one has tried to open, for instance,
+ '/dev/kbus9' when there are only 3 KBUS devices).
+:ENOLCK: On attempting to send a Request, when there is not enough room
+ in the sender's message queue to guarantee that it can
+ receive a reply for every Request already sent, *plus* this
+ one. If there are oustanding messages in the sender's message
+ queue, then the solution is to read some of them. Otherwise,
+ the sender will have to wait until one of the Repliers
+ replies to a previous Request (or goes away and KBUS replies
+ for it).
+
+ When this error is received, the send has failed (just as if
+ the message was invalid). The sender is not left in "sending"
+ state, nor has the message been assigned a message id.
+
+ Note that this is *not* EAGAIN, since we do not want to block
+ the sender (in the SEND) if it is up to the sender to perform
+ a read to sort things out.
+
+:ENOMSG: On attempting to send, when there is no message waiting to be
+ sent (either because there has been no write since the last
+ send, or because the message being written has been
+ discarded).
+:EPIPE: On attempting to send 'to' a specific replier, the replier
+ with that id is no longer bound to the given message's name.
+
+:EFAULT: Memory allocation, copy from user space, or other such failed. This
+ is normally very bad, it should not happen, UNLESS it is the result
+ of calling an ioctl, when it indicates that the ioctl argument
+ cannot be accessed.
+
+:ENOMEM: Memory allocation failed (return NULL). This is normally very bad,
+ it should not happen.
+
+:EAGAIN: On attempting to send, the message being sent had ALL_OR_WAIT set,
+ and one of the targetted listener/replier queues was full.
+
+ On attempting to unbind when Replier Bind Events have been
+ requested, one or more of the KSocks bound to receive
+ "$.KBUS.ReplierBindEvent" messages has a full message queue,
+ and thus cannot receive the unbind event. The unbind has not been
+ done.
+
+In the ``utils`` directory of the KBUS sources, there is a script called
+``errno.py`` which takes an ``errno`` integer or name and prints out both the
+"normal" meaning of that error number, and also (if there is one) the KBUS use
+of it. For instance::
+
+ $ errno.py 1
+ Error 1 (0x1) is EPERM: Operation not permitted
+ $
+ $ errno.py EPIPE
+ EPIPE is error 32 (0x20): Broken pipe
+
+ KBUS:
+ On attempting to send 'to' a specific replier, the replier with that id
+ is no longer bound to the given message's name.
+
--
1.7.1
^ permalink raw reply related
* [PATCH 0/5] RFC: KBUS messaging subsystem
From: Tony Ibbs @ 2011-02-27 18:11 UTC (permalink / raw)
To: Linux-embedded; +Cc: Tibs at Kynesim, Richard Watts, Grant Likely
KBUS is a lightweight, Linux kernel mediated, message system,
particularly intended for use in embedded environments.
It is meant to be simple to use and understand. It is designed to
provide predictable message delivery, deterministic message ordering,
and a guaranteed reply for each request.
It is especially aimed at situations where existing solutions,
such as DBUS, cannot be used, typically because of system constraints.
We have various customers using KBUS in real life, and believe it to
be useful. I had a showcase table for KBUS at the ELCE in Cambridge,
October last year, and there seemed to be interest.
I am hoping to get a response from this list before attempting to send
to the kernel list, since I believe this list should contain people
who might be most interested in using it.
The KBUS project home page is at http://kbus-messaging.org/, from
which there are various useful links.
There is a working repository with Linux 2.6.37 patched for KBUS,
available via:
git pull git://github.com/crazyscot/linux-2.6-kbus.git kbus-2.6.37
This is a resubmission of the original RFC to the Linux-Embedded list,
having:
a) changed to use __u32 instead of uint32_t and
b) changed to use kernel messaging mechanisms (also removing
some messaging that should not be needed). These in response
to the suggestion of Sam Ravnborg
c) split into multiple in-line patches, as is normal practice,
and as requested by Grant Likely
Tibs (5):
Documentation for KBUS
External header file for KBUS
Kconfig files and Makefile for KBUS
Internal header file for KBUS
KBUS itself, the main source file
Documentation/Kbus.txt | 1222 +++++++++++
include/linux/kbus_defns.h | 666 ++++++
init/Kconfig | 3 +
ipc/Kconfig | 99 +
ipc/Makefile | 5 +
ipc/kbus.c | 4927 ++++++++++++++++++++++++++++++++++++++++++++
ipc/kbus_internal.h | 709 +++++++
7 files changed, 7631 insertions(+), 0 deletions(-)
create mode 100644 Documentation/Kbus.txt
create mode 100644 include/linux/kbus_defns.h
create mode 100644 ipc/Kconfig
create mode 100644 ipc/kbus.c
create mode 100644 ipc/kbus_internal.h
^ permalink raw reply
* Re: [PWM v6 0/3] Implement a generic PWM framework
From: Mike Frysinger @ 2011-02-27 17:48 UTC (permalink / raw)
To: Bill Gatliff; +Cc: linux-embedded
In-Reply-To: <AANLkTimwS+KsB3uRinY2WVzXQ6ZsuhY0ySAmHquTWff6@mail.gmail.com>
On Fri, Feb 25, 2011 at 21:38, Bill Gatliff wrote:
> On Sun, Feb 20, 2011 at 9:35 PM, Bill Gatliff wrote:
>> This patch series contains the sixth attempt at implementation of
>> a generic PWM device interface framework. Think gpiolib, but for
>> devices and pseudo-devices that generate pulse-wave-modulated outputs.
>
> Hearing no objections, does this mean that this code is finally ready
> for a pull request? To whom do I send it?
i'd start with akpm/lkml/linus and add yourself to MAINTAINERS for the
pwm framework
-mike
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Mark Brown @ 2011-02-26 9:45 UTC (permalink / raw)
To: Bill Gatliff; +Cc: linux-input, linux-embedded
In-Reply-To: <AANLkTikWA3Vsa2O4_yi1L78_xX18_7WqVKqhTaD1-6Wm@mail.gmail.com>
On Fri, Feb 25, 2011 at 08:46:24PM -0600, Bill Gatliff wrote:
> On Mon, Feb 21, 2011 at 10:33 PM, Mark Brown
> <broonie@opensource.wolfsonmicro.com> wrote:
> > But surely the most obvious solution here is to standardise a rate
> > control interface?
> Yes, and no. A standardized rate control interface would deal with
> the rate control problem, but leave the synchronization problem
> unsolved.
The main source of the problem with delayed readings was that
applications weren't blocking waiting for events. If applications block
waiting for events then the data will be delivered to them promptly.
For cases where multiple readings need to be synced IIO looks like the
way forward.
> > The problem you're trying to solve is also an issue for really common
> > and standard things like touchscreens and polled switches/keys (the
> > latter of which you mentioned in your mail) which are used by standard
> > applications.
> The existing "polled switch" implementation sets up a throttled
> polling loop in kernel code. The "polled switch" that I was thinking
> of when I wrote the essay for the commit was "a switch that is polled
> each time read() gets called". I should have been clearer--- and
> probably picked a different name. :)
It's the same thing, though - I'd really expect it to be handled by the
same code in kernel.
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Bill Gatliff @ 2011-02-26 2:49 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-input, linux-embedded
In-Reply-To: <4D63B663.6070308@cam.ac.uk>
Jonathan:
On Tue, Feb 22, 2011 at 7:13 AM, Jonathan Cameron <jic23@cam.ac.uk> wrote:
> Hmm. We still need to do more work on this to get it to the level I'd like.
I've been looking at the iio code some. Honestly, I don't grok it at
all yet. :)
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Bill Gatliff @ 2011-02-26 2:46 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-input, linux-embedded
In-Reply-To: <20110222043302.GD18299@sirena.org.uk>
Mark:
On Mon, Feb 21, 2011 at 10:33 PM, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
>
> But surely the most obvious solution here is to standardise a rate
> control interface?
Yes, and no. A standardized rate control interface would deal with
the rate control problem, but leave the synchronization problem
unsolved.
> The problem you're trying to solve is also an issue for really common
> and standard things like touchscreens and polled switches/keys (the
> latter of which you mentioned in your mail) which are used by standard
> applications.
The existing "polled switch" implementation sets up a throttled
polling loop in kernel code. The "polled switch" that I was thinking
of when I wrote the essay for the commit was "a switch that is polled
each time read() gets called". I should have been clearer--- and
probably picked a different name. :)
> Have you looked at the IIO subsystem for things like this? There has
> been talk of putting accelerometers in there and it certainly fits in
> with the sync requirements you're mentioning.
Now that I have found the code, I'm looking at it. Can't say yet
whether it's the solution I'm seeking, or not.
> The problem with your proposal as it stands is that if they do use the
> new interface they interact badly with existing applications. This
> isn't really a decision the driver should be taking, it needs to be
> userspace policy if it's going to be a decision at all.
Yea, I'm agreeing with you more than I was at the beginning of this thread.
b.g.
--
Bill Gatliff
bgat@billgatliff.com
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PWM v6 0/3] Implement a generic PWM framework
From: Bill Gatliff @ 2011-02-26 2:38 UTC (permalink / raw)
To: linux-embedded
In-Reply-To: <1298259345-9794-1-git-send-email-bgat@billgatliff.com>
Guys:
On Sun, Feb 20, 2011 at 9:35 PM, Bill Gatliff <bgat@billgatliff.com> wrote:
> This patch series contains the sixth attempt at implementation of
> a generic PWM device interface framework. Think gpiolib, but for
> devices and pseudo-devices that generate pulse-wave-modulated outputs.
Hearing no objections, does this mean that this code is finally ready
for a pull request? To whom do I send it?
Thanks!
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Jonathan Cameron @ 2011-02-22 13:13 UTC (permalink / raw)
To: Mark Brown; +Cc: Bill Gatliff, linux-input, linux-embedded
In-Reply-To: <20110222043302.GD18299@sirena.org.uk>
On 02/22/11 04:33, Mark Brown wrote:
> On Mon, Feb 21, 2011 at 10:07:12PM -0600, Bill Gatliff wrote:
>
>> A good case in point comes up when someone moves an Android
>> implementation from one platform to another. No two accelerometer
>> drivers seem to agree on how to specify the desired event generation
>> rate, so the migration effort is increased. And the work is divided
>> between both kernel and userspace: the former in its mandate to
>> provide a rate-request interface, and the latter to utilize that
>> interface. I really don't see the point in this.
>
> But surely the most obvious solution here is to standardise a rate
> control interface? Anything else means we need a completely different
> implementation for hardware which does have the ability to schedule its
> own conversions.
I agree that standardizing would be a good idea. Note that far from all
accelerometers act as 'polled' devices. Most I've encountered have their
own sampling clocks and in many cases these can be set pretty low, saving
power and sometimes applying filters to give lower noise on the output.
For these I don't think the approach given in this thread makes sense.
It's more promising for those devices that are using an in driver
polling thread that actually initializes the sampling (more common
in slow devices like magnetometers). Still, whilst I initially liked
the idea, the whole point about it interoperating badly with apps that
are event driven is clearly a big issue...
>
>> As I mention in my commit log/essay, devices like USB keyboards and
>> other event-driven hardware have no use for my read callback idea, and
>> can safely ignore it. And I don't see a day on the horizon where
>> anyone will plug an accelerometer into X and expect X to deal with it
>> as properly as it does today for keyboards and mice. I don't think
>> the "do the right thing" applications you are referring to will be
>> affected by the read callback at all, since the callback doesn't apply
>> to ordinary, "do the right thing"-type situations.
>
> The problem you're trying to solve is also an issue for really common
> and standard things like touchscreens and polled switches/keys (the
> latter of which you mentioned in your mail) which are used by standard
> applications.
>
>> But if the accelerometer measurement has to be synchronized with some
>> other event, things get a little trickier. At the moment my concerns
>> for this are theoretical, but I can see some situations coming soon
>> where the theory could be usefully put to practice.
>
> Have you looked at the IIO subsystem for things like this? There has
> been talk of putting accelerometers in there and it certainly fits in
> with the sync requirements you're mentioning.
Hmm. We still need to do more work on this to get it to the level I'd like.
To give background info:
A common reason for wanting this is Inertial Measurement Units (combination
of typically accelerometers, gyros and magnetometers) made up of a number
of discrete parts. Some of these will run on their own internal clocks, so
not much we can do about them, but others as for the devices you are considering
here will sample based on a trigger pin, command over bus, or the bus read
itself.
IIO handles this via 'triggers'. These are provided either by hardware
(data ready signals from chips, or gpio pins), timers or userspace triggering.
Any trigger can have as many separate poll functions attached as you like,
allowing the 'trigger event' to cause data to be captured from lots of different
sensors. There are two queues, one for hammering capture pins as fast as possible
and one for doing slower bus based reads. Aim is to get all the captures as close
as possible together subject to constraints of the actual board.
Things we don't handle well:
* delays. Some devices have deterministic capture delays. Ideally we would take
these into account though it isn't entirely clear what the desired behaviour actually
is.
* Triggering based on the data ready signal of a part that isn't attached to the
same trigger. This is fiddly and right now you can end up with the trigger not being
cleared and hence only firing once.
* Triggering form more esoteric events. E.g. Grab values from one device when another
passes some threshold. However these will only be added if anyone actually has a use
case and even then will require support in the particular parts driver.
Still, it's a work in progress...
>
>>> If the application were to use a rate control in conjunction with blocking
>>> (which is the expected programming model) then a rate control will do
>>> exactly what's expected.
>
>> No argument with that. My main complaint is that everyone is doing
>> rate control APIs differently. I'm proposing a way to standardize
>> them by eliminating them altogether. A side-effect of my idea is that
>> applications get complete control over event generation. Many of them
>> won't care about that, but some will.
>
> The problem with your proposal as it stands is that if they do use the
> new interface they interact badly with existing applications. This
> isn't really a decision the driver should be taking, it needs to be
> userspace policy if it's going to be a decision at all.
>
>> I recognize your concern. But I don't think that the applications
>> which could be confused by the behavior I'm proposing would be the
>> same applications that would take advantage of it. Or, perhaps, such
>> applications might welcome eliminating the code needed to support the
>> different rate-limiting interfaces of a half-dozen or more devices
>> that they claim compatibility with.
>
> Again, you appear to be assuming that there are many rate limiting
> interfaces. Surely the solution to an excess of rate limit interfaces
> is to standardise the rate limiting interfaces rather than invent a new
> interface, especially one that interoperates poorly with blocking apps?
>
>>> This is all stuff that can be put into a library (parts of it are
>>> already) so there's no real cost to drivers from implementing anything.
>
>> ... except the redundancy of everyone doing it slightly differently.
>> Why not settle on a common approach, so the library you mention isn't
>> necessary at all?
>
> Note that I'm talking about in-kernel code here, not a linked library in
> userspace. One way or another *something* is going to have to provide
> the scheduling support.
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Mark Brown @ 2011-02-22 4:33 UTC (permalink / raw)
To: Bill Gatliff; +Cc: linux-input, linux-embedded
In-Reply-To: <AANLkTik8d1KZd_qSr2tKrBHq2X-9agA1BG7guK1SqzAd@mail.gmail.com>
On Mon, Feb 21, 2011 at 10:07:12PM -0600, Bill Gatliff wrote:
> A good case in point comes up when someone moves an Android
> implementation from one platform to another. No two accelerometer
> drivers seem to agree on how to specify the desired event generation
> rate, so the migration effort is increased. And the work is divided
> between both kernel and userspace: the former in its mandate to
> provide a rate-request interface, and the latter to utilize that
> interface. I really don't see the point in this.
But surely the most obvious solution here is to standardise a rate
control interface? Anything else means we need a completely different
implementation for hardware which does have the ability to schedule its
own conversions.
> As I mention in my commit log/essay, devices like USB keyboards and
> other event-driven hardware have no use for my read callback idea, and
> can safely ignore it. And I don't see a day on the horizon where
> anyone will plug an accelerometer into X and expect X to deal with it
> as properly as it does today for keyboards and mice. I don't think
> the "do the right thing" applications you are referring to will be
> affected by the read callback at all, since the callback doesn't apply
> to ordinary, "do the right thing"-type situations.
The problem you're trying to solve is also an issue for really common
and standard things like touchscreens and polled switches/keys (the
latter of which you mentioned in your mail) which are used by standard
applications.
> But if the accelerometer measurement has to be synchronized with some
> other event, things get a little trickier. At the moment my concerns
> for this are theoretical, but I can see some situations coming soon
> where the theory could be usefully put to practice.
Have you looked at the IIO subsystem for things like this? There has
been talk of putting accelerometers in there and it certainly fits in
with the sync requirements you're mentioning.
> > If the application were to use a rate control in conjunction with blocking
> > (which is the expected programming model) then a rate control will do
> > exactly what's expected.
> No argument with that. My main complaint is that everyone is doing
> rate control APIs differently. I'm proposing a way to standardize
> them by eliminating them altogether. A side-effect of my idea is that
> applications get complete control over event generation. Many of them
> won't care about that, but some will.
The problem with your proposal as it stands is that if they do use the
new interface they interact badly with existing applications. This
isn't really a decision the driver should be taking, it needs to be
userspace policy if it's going to be a decision at all.
> I recognize your concern. But I don't think that the applications
> which could be confused by the behavior I'm proposing would be the
> same applications that would take advantage of it. Or, perhaps, such
> applications might welcome eliminating the code needed to support the
> different rate-limiting interfaces of a half-dozen or more devices
> that they claim compatibility with.
Again, you appear to be assuming that there are many rate limiting
interfaces. Surely the solution to an excess of rate limit interfaces
is to standardise the rate limiting interfaces rather than invent a new
interface, especially one that interoperates poorly with blocking apps?
> > This is all stuff that can be put into a library (parts of it are
> > already) so there's no real cost to drivers from implementing anything.
> ... except the redundancy of everyone doing it slightly differently.
> Why not settle on a common approach, so the library you mention isn't
> necessary at all?
Note that I'm talking about in-kernel code here, not a linked library in
userspace. One way or another *something* is going to have to provide
the scheduling support.
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Bill Gatliff @ 2011-02-22 4:07 UTC (permalink / raw)
To: Mark Brown; +Cc: linux-input, linux-embedded
In-Reply-To: <20110222002315.GA18299@sirena.org.uk>
Mark:
Thanks for the great feedback!
In a nutshell, I agree with your summary stating that my proposal "is
going to cause problems for applications that try to do the right
thing". Were my suggestion to be adopted immediately and across the
board, things would turn hairy indeed!
I'm actually focused on a very narrow use case, however:
accelerometers, compasses, polled switches, and similar hardware. I'm
wanting to propose a common method for dealing with these, as an
alternative to the raft of incompatible approaches that are currently
taking hold. And in addition to avoiding the inconsistency of these
implementations across devices, I also want to eliminate as much
redundancy in the implementations as possible.
A good case in point comes up when someone moves an Android
implementation from one platform to another. No two accelerometer
drivers seem to agree on how to specify the desired event generation
rate, so the migration effort is increased. And the work is divided
between both kernel and userspace: the former in its mandate to
provide a rate-request interface, and the latter to utilize that
interface. I really don't see the point in this.
Granted, on all of MY platforms I can go ahead and implement this
read-callback idea, and so far it has proven interesting and helpful.
I'm just thinking that my success could appeal to a wider audience.
Instead of all of us creating and repeating the same work over and
over again, let's agree on SOMETHING. Mine is of course a
somewhat-different way of solving the problem, but not without merit.
As I mention in my commit log/essay, devices like USB keyboards and
other event-driven hardware have no use for my read callback idea, and
can safely ignore it. And I don't see a day on the horizon where
anyone will plug an accelerometer into X and expect X to deal with it
as properly as it does today for keyboards and mice. I don't think
the "do the right thing" applications you are referring to will be
affected by the read callback at all, since the callback doesn't apply
to ordinary, "do the right thing"-type situations.
More responses inline below:
On Mon, Feb 21, 2011 at 6:23 PM, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
> I don't see how any of the above shows an issue with rate limiting in
> the application image. As was discussed in some detail the last time
> you posted this the issue that's causing the applications to experience
> delayed notifications of events is that rather than blocking waiting for
> an event to be delivered to them they're sleeping unconditionally.
That is definitely one source of problems.
But if the accelerometer measurement has to be synchronized with some
other event, things get a little trickier. At the moment my concerns
for this are theoretical, but I can see some situations coming soon
where the theory could be usefully put to practice.
> If the application were to use a rate control in conjunction with blocking
> (which is the expected programming model) then a rate control will do
> exactly what's expected.
No argument with that. My main complaint is that everyone is doing
rate control APIs differently. I'm proposing a way to standardize
them by eliminating them altogether. A side-effect of my idea is that
applications get complete control over event generation. Many of them
won't care about that, but some will.
> This doesn't address the issue raised in the previous discussion with
> the poor interaction with applications that do behave sensibly and block
> for events from the device - either we can't use the ability to trigger
> readings from the hardware or we end up doing extra readings because
> every read triggers an additional sample.
I recognize your concern. But I don't think that the applications
which could be confused by the behavior I'm proposing would be the
same applications that would take advantage of it. Or, perhaps, such
applications might welcome eliminating the code needed to support the
different rate-limiting interfaces of a half-dozen or more devices
that they claim compatibility with.
Besides, it isn't like my proposal would be forced upon any of the
existing mainline drivers. Most of them, like keyboards and mice,
couldn't use it anyway.
> This is all stuff that can be put into a library (parts of it are
> already) so there's no real cost to drivers from implementing anything.
... except the redundancy of everyone doing it slightly differently.
Why not settle on a common approach, so the library you mention isn't
necessary at all?
> This will again interact poorly with event driven applications - if
> notifications to userspace don't happen (eg, because there has been no
> change) then there will be no cause for the application to read.
Agreed. But those situations don't describe users of accelerometers
and compasses. At least not in the code/situations I have
encountered.
> I can see a use for a read on demand callback in the implementation of
> polling (eg, if rate is set to zero or for the core polling library to
> use) but the userspace API thats being proposed here seems like it's
> going to cause problems for applications that try to do the right thing.
Such applications probably aren't a factor here.
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* Re: [PATCH] input: evdev: Add a read() callback
From: Mark Brown @ 2011-02-22 0:23 UTC (permalink / raw)
To: Bill Gatliff; +Cc: linux-input, linux-embedded
In-Reply-To: <1298297930-3937-1-git-send-email-bgat@billgatliff.com>
On Mon, Feb 21, 2011 at 08:18:50AM -0600, Bill Gatliff wrote:
> But implementing a rate-specifying sysfs attribute isn't enough,
> however. Under the Linux kernel's current input device buffering
> scheme, drivers and applications can create and consume input events
> every 100ms, for example, but there is always the possibility that an
> input event will sit in the queue for 99ms waiting for an application
> to retrieve it. For devices and applications where this potential
> delay causes problems, drivers must implement an external means for
> applications to trigger the timely production of an input event.
I don't see how any of the above shows an issue with rate limiting in
the application image. As was discussed in some detail the last time
you posted this the issue that's causing the applications to experience
delayed notifications of events is that rather than blocking waiting for
an event to be delivered to them they're sleeping unconditionally. If
the application were to use a rate control in conjunction with blocking
(which is the expected programming model) then a rate control will do
exactly what's expected.
> The enclosed patch address all of the above problems by implementing
> an advisory callback from the evdev read() and poll() methods to the
> associated input device driver. The driver may then choose to
> populate the input event buffer at that time, rather than on a
> schedule implemented by a polling loop, sysfs trigger, or other means.
> Use of this callback by a driver naturally synchronizes the generation
> of input events to requests from userspace, because the driver now
> "knows" when userspace is attempting to retrieve an input event and
> can therefore produce one just-in-time. It also allows the driver to
> easily match the rate of input event generation, by simply sampling the
> hardware only during this callback.
This doesn't address the issue raised in the previous discussion with
the poor interaction with applications that do behave sensibly and block
for events from the device - either we can't use the ability to trigger
readings from the hardware or we end up doing extra readings because
every read triggers an additional sample.
> If an input device driver chooses to use only the read() callback as
> its signal to produce an input event, then the driver need not
> implement a polling kernel thread or other means of pacing its event
> generation rate. The driver also has no need to provide a sysfs
> attribute to allow userspace to request a polling rate or to trigger a
> measurement: userspace must only read() or poll() the interface at the
> desired rate. This can greatly simplify input device driver
> implementation, while conveniently leaving the incoming event rate and
This is all stuff that can be put into a library (parts of it are
already) so there's no real cost to drivers from implementing anything.
> Finally, input device drivers might choose to implement a holdoff
> timer that gets reset in the read() callback; expiration of this timer
> would mean that userspace is no longer actively reading from the
> device, even though the interface itself might still be open. In such
> cases the driver might wish to invoke a power-management method to
> idle the hardware until the next callback occurs.
This will again interact poorly with event driven applications - if
notifications to userspace don't happen (eg, because there has been no
change) then there will be no cause for the application to read.
I can see a use for a read on demand callback in the implementation of
polling (eg, if rate is set to zero or for the core polling library to
use) but the userspace API thats being proposed here seems like it's
going to cause problems for applications that try to do the right thing.
^ permalink raw reply
* Re: [PWM v5 1/3] PWM: Implement a generic PWM framework
From: Bill Gatliff @ 2011-02-21 4:42 UTC (permalink / raw)
To: Mike Frysinger; +Cc: linux-embedded
In-Reply-To: <AANLkTi=egAxrcGxRsAqYwnv0=DgxQuL_Gqd5-AR7=3Zg@mail.gmail.com>
Mike:
On Sun, Feb 20, 2011 at 9:33 PM, Mike Frysinger <vapier.adi@gmail.com> wrote:
> On Sun, Feb 20, 2011 at 22:18, Bill Gatliff wrote:
>> On Sun, Feb 20, 2011 at 4:46 PM, Mike Frysinger <vapier.adi@gmail.com> wrote:
>>>> +static const struct attribute_group pwm_device_attr_group = {
>>>> + .attrs = (struct attribute **) pwm_attrs,
>>>> +};
>>>
>>> should attribute_group have its attrs member constified ?
>>
>> Isn't it already, given that the pwm_device_attr_group definition is const?
>
> if it were already, you wouldnt need that cast
Aah, so you are suggesting that I patch the attribute_group structure
definition, no?
Scary. Not. My. Code. :)
b.g.
--
Bill Gatliff
bgat@billgatliff.com
^ permalink raw reply
* [PATCH] input: evdev: Add a read() callback
From: Bill Gatliff @ 2011-02-21 4:42 UTC (permalink / raw)
To: linux-embedded; +Cc: Bill Gatliff
Some devices, like accelerometers, can manufacture as many input
events as userspace can consume. The traditional method for limiting
the number of input events sent to userspace by such devices is to use
a kernel thread looping around an idle timer, to "throttle" the
creation and queuing of input events to a manageable rate. Such
drivers often also provide a sysfs attribute (or similar means) that
allows userspace to indicate a desired event rate.
Some operating systems and/or applications e.g. Android, might prefer
to control input event creation rates themselves. They frequently
attempt to do so by implementing a userspace polling thread that loops
around an idle timer; this idle timer throttles the rate of calls to
the input devices' read() method, which (at least in theory) limits
the rate of input events arriving at the application to a desired
level.
In practice, you want to use only one of the two aforementioned
approaches; if you try to do both, you'll get event buffer overflows,
weird behaviors, and delay stackups as the two timers apply their rate
limiting throttles against each other.
Userspace throttling of input events doesn't work very well with the
Linux kernel's current input event buffering scheme, because there is
no direct connection between the read() system call and the driver for
the input device being queried. Put simply, current input device
drivers simply cannot tell when--- or even if--- userspace is polling
for an input event.
But implementing a rate-specifying sysfs attribute isn't enough,
however. Under the Linux kernel's current input device buffering
scheme, drivers and applications can create and consume input events
every 100ms, for example, but there is always the possibility that an
input event will sit in the queue for 99ms waiting for an application
to retrieve it. For devices and applications where this potential
delay causes problems, drivers must implement an external means for
applications to trigger the timely production of an input event.
The enclosed patch address all of the above problems by implementing
an advisory callback from the evdev read() and poll() methods to the
associated input device driver. The driver may then choose to
populate the input event buffer at that time, rather than on a
schedule implemented by a polling loop, sysfs trigger, or other means.
Use of this callback by a driver naturally synchronizes the generation
of input events to requests from userspace, because the driver now
"knows" when userspace is attempting to retrieve an input event and
can therefore produce one just-in-time. It also allows the driver to
easily match the rate of input event generation, by simply sampling the
hardware only during this callback.
If an input device driver chooses to use only the read() callback as
its signal to produce an input event, then the driver need not
implement a polling kernel thread or other means of pacing its event
generation rate. The driver also has no need to provide a sysfs
attribute to allow userspace to request a polling rate or to trigger a
measurement: userspace must only read() or poll() the interface at the
desired rate. This can greatly simplify input device driver
implementation, while conveniently leaving the incoming event rate and
synchronization issues completely up to the application. (See POSIX.1b
interval timers and scheduler options for APIs allowing precise timing
within user applications).
Finally, input device drivers might choose to implement a holdoff
timer that gets reset in the read() callback; expiration of this timer
would mean that userspace is no longer actively reading from the
device, even though the interface itself might still be open. In such
cases the driver might wish to invoke a power-management method to
idle the hardware until the next callback occurs.
Polled devices like accelerometers and compasses (and perhaps some
types of pushbuttons or switch inputs) will get the most benefit from
utilizing the read() callback. Other devices, like USB keyboards and
mice, will have no use for it and may safely ignore it.
Signed-off-by: Bill Gatliff <bgat@billgatliff.com>
---
drivers/input/evdev.c | 10 ++++++++++
include/linux/input.h | 1 +
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c8471a2..b49b601 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -370,12 +370,19 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
{
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
+ struct input_dev *dev = evdev->handle.dev;
struct input_event event;
int retval;
if (count < input_event_size())
return -EINVAL;
+ if (client->head == client->tail && dev->read) {
+ retval = dev->read(dev);
+ if (retval)
+ return retval;
+ }
+
if (client->head == client->tail && evdev->exist &&
(file->f_flags & O_NONBLOCK))
return -EAGAIN;
@@ -407,6 +414,9 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
struct evdev *evdev = client->evdev;
unsigned int mask;
+ if (client->head == client->tail && dev->read)
+ dev->read(dev);
+
poll_wait(file, &evdev->wait, wait);
mask = evdev->exist ? POLLOUT | POLLWRNORM : POLLHUP | POLLERR;
diff --git a/include/linux/input.h b/include/linux/input.h
index e428382..eac7f77 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1264,6 +1264,7 @@ struct input_dev {
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
+ int (*read)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
--
1.7.2.3
^ permalink raw reply related
* [PWM v6 3/3] PWM: Atmel PWMC driver
From: Bill Gatliff @ 2011-02-21 3:35 UTC (permalink / raw)
To: linux-embedded; +Cc: Bill Gatliff
In-Reply-To: <1298259345-9794-1-git-send-email-bgat@billgatliff.com>
Driver to allow the Atmel PWMC peripheral found on various
AT91 SoCs to be controlled using the Generic PWM framework.
Tested on the AT91SAM9263.
Signed-off-by: Bill Gatliff <bgat@billgatliff.com>
---
drivers/pwm/Kconfig | 8 +
drivers/pwm/Makefile | 1 +
drivers/pwm/atmel-pwmc.c | 494 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 503 insertions(+), 0 deletions(-)
create mode 100644 drivers/pwm/atmel-pwmc.c
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 476de67..560324a 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -19,3 +19,11 @@ config GPIO_PWM
To compile this feature as a module, chose M here; the module
will be called gpio-pwm. If unsure, say N.
+
+config ATMEL_PWMC
+ tristate "Atmel AT32/AT91 PWMC support"
+ depends on GENERIC_PWM && (AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9)
+ help
+ This option enables support under the generic PWM
+ framework for PWMC peripheral channels found on
+ certain Atmel microcontrollers. If unsure, say N.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index ecec3e4..d274fa0 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_GENERIC_PWM) := pwm.o
obj-$(CONFIG_GPIO_PWM) += gpio-pwm.o
+obj-$(CONFIG_ATMEL_PWMC) += atmel-pwmc.o
diff --git a/drivers/pwm/atmel-pwmc.c b/drivers/pwm/atmel-pwmc.c
new file mode 100644
index 0000000..491ec88
--- /dev/null
+++ b/drivers/pwm/atmel-pwmc.c
@@ -0,0 +1,494 @@
+/*
+ * Atmel PWMC peripheral driver
+ *
+ * Copyright (C) 2011 Bill Gatliff <bgat@billgatliff.com>
+ * Copyright (C) 2007 David Brownell
+ *
+ * This program is free software; you may redistribute and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/pwm/pwm.h>
+
+enum {
+ /* registers common to the PWMC peripheral */
+ PWMC_MR = 0,
+ PWMC_ENA = 4,
+ PWMC_DIS = 8,
+ PWMC_SR = 0xc,
+ PWMC_IER = 0x10,
+ PWMC_IDR = 0x14,
+ PWMC_IMR = 0x18,
+ PWMC_ISR = 0x1c,
+
+ /* registers per each PWMC channel */
+ PWMC_CMR = 0,
+ PWMC_CDTY = 4,
+ PWMC_CPRD = 8,
+ PWMC_CCNT = 0xc,
+ PWMC_CUPD = 0x10,
+
+ /* how to find each channel */
+ PWMC_CHAN_BASE = 0x200,
+ PWMC_CHAN_STRIDE = 0x20,
+
+ /* CMR bits of interest */
+ PWMC_CMR_CPD = 10,
+ PWMC_CMR_CPOL = 9,
+ PWMC_CMR_CALG = 8,
+ PWMC_CMR_CPRE_MASK = 0xf,
+};
+
+/* TODO: NCHAN==4 only for certain AT91-ish parts! */
+#define NCHAN 4
+struct atmel_pwmc {
+ struct pwm_device p[NCHAN];
+ struct pwm_device_ops ops;
+ spinlock_t lock;
+ struct completion complete;
+ void __iomem *iobase;
+ struct clk *clk;
+ int irq;
+ u32 ccnt_mask;
+};
+
+/* TODO: debugfs attributes for peripheral register values */
+
+static inline void pwmc_writel(const struct atmel_pwmc *p, unsigned offset, u32 val)
+{
+ __raw_writel(val, p->iobase + offset);
+}
+
+static inline u32 pwmc_readl(const struct atmel_pwmc *p, unsigned offset)
+{
+ return __raw_readl(p->iobase + offset);
+}
+
+static void pwmc_chan_writel(const struct pwm_device *p,
+ u32 offset, u32 val)
+{
+ const struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int chan = p - &ap->p[0];
+
+ if (PWMC_CMR == offset)
+ val &= ((1 << PWMC_CMR_CPD)
+ | (1 << PWMC_CMR_CPOL)
+ | (1 << PWMC_CMR_CALG)
+ | (PWMC_CMR_CPRE_MASK));
+ else
+ val &= ap->ccnt_mask;
+
+ pwmc_writel(ap, offset + PWMC_CHAN_BASE
+ + (chan * PWMC_CHAN_STRIDE), val);
+}
+
+static u32 pwmc_chan_readl(const struct pwm_device *p, u32 offset)
+{
+ const struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int chan = p - &ap->p[0];
+
+ return pwmc_readl(ap, offset + PWMC_CHAN_BASE
+ + (chan * PWMC_CHAN_STRIDE));
+}
+
+static int __atmel_pwmc_is_on(struct pwm_device *p)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int chan = p - &ap->p[0];
+
+ return (pwmc_readl(ap, PWMC_SR) & BIT(chan)) ? 1 : 0;
+}
+
+static void __atmel_pwmc_stop(struct pwm_device *p)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int chan = p - &ap->p[0];
+
+ pwmc_writel(ap, PWMC_DIS, BIT(chan));
+}
+
+static void __atmel_pwmc_start(struct pwm_device *p)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int chan = p - &ap->p[0];
+
+ pwmc_writel(ap, PWMC_ENA, BIT(chan));
+}
+
+static void __atmel_pwmc_config_polarity(struct pwm_device *p,
+ struct pwm_config *c)
+{
+ unsigned long cmr = pwmc_chan_readl(p, PWMC_CMR);
+
+ if (c->polarity)
+ clear_bit(PWMC_CMR_CPOL, &cmr);
+ else
+ set_bit(PWMC_CMR_CPOL, &cmr);
+ pwmc_chan_writel(p, PWMC_CMR, cmr);
+ p->active_high = c->polarity ? 1 : 0;
+
+ dev_dbg(p->dev, "polarity %d\n", c->polarity);
+}
+
+static void __atmel_pwmc_config_duty_ticks(struct pwm_device *p,
+ struct pwm_config *c)
+{
+ unsigned long cmr, cprd, cpre, cdty;
+
+ cmr = pwmc_chan_readl(p, PWMC_CMR);
+ cprd = pwmc_chan_readl(p, PWMC_CPRD);
+
+ cpre = cmr & PWMC_CMR_CPRE_MASK;
+ clear_bit(PWMC_CMR_CPD, &cmr);
+
+ cdty = cprd - (c->duty_ticks >> cpre);
+
+ p->duty_ticks = c->duty_ticks;
+
+ if (__atmel_pwmc_is_on(p)) {
+ pwmc_chan_writel(p, PWMC_CMR, cmr);
+ pwmc_chan_writel(p, PWMC_CUPD, cdty);
+ } else
+ pwmc_chan_writel(p, PWMC_CDTY, cdty);
+
+ dev_dbg(p->dev, "duty_ticks = %lu cprd = %lx"
+ " cdty = %lx cpre = %lx\n", p->duty_ticks,
+ cprd, cdty, cpre);
+}
+
+static void __atmel_pwmc_config_period_ticks(struct pwm_device *p,
+ struct pwm_config *c)
+{
+ u32 cmr, cprd, cpre;
+
+ cpre = fls(c->period_ticks);
+ if (cpre < 16)
+ cpre = 0;
+ else {
+ cpre -= 15;
+ if (cpre > 10)
+ return -EINVAL;
+ }
+
+ cmr = pwmc_chan_readl(p, PWMC_CMR);
+ cmr &= ~PWMC_CMR_CPRE_MASK;
+ cmr |= cpre;
+
+ cprd = c->period_ticks >> cpre;
+
+ pwmc_chan_writel(p, PWMC_CMR, cmr);
+ pwmc_chan_writel(p, PWMC_CPRD, cprd);
+ p->period_ticks = c->period_ticks;
+
+ dev_dbg(p->dev, "period_ticks = %lu cprd = %x cpre = %x\n",
+ p->period_ticks, cprd, cpre);
+}
+
+static int atmel_pwmc_config_nosleep(struct pwm_device *p, struct pwm_config *c)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int ret = 0;
+ unsigned long flags;
+ int chan = p - &ap->p[0];
+
+ spin_lock_irqsave(&ap->lock, flags);
+
+ switch (c->config_mask) {
+
+ case BIT(PWM_CONFIG_DUTY_TICKS):
+ __atmel_pwmc_config_duty_ticks(p, c);
+ break;
+
+ case BIT(PWM_CONFIG_STOP):
+ __atmel_pwmc_stop(p);
+ break;
+
+ case BIT(PWM_CONFIG_START):
+ __atmel_pwmc_start(p);
+ break;
+
+ case BIT(PWM_CONFIG_POLARITY):
+ __atmel_pwmc_config_polarity(p, c);
+ break;
+
+ case BIT(PWM_CONFIG_ENABLE_CALLBACK):
+ pwmc_writel(ap, PWMC_IER, BIT(chan));
+ break;
+
+ case BIT(PWM_CONFIG_DISABLE_CALLBACK):
+ pwmc_writel(ap, PWMC_IDR, BIT(chan));
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&ap->lock, flags);
+ return ret;
+}
+
+static int atmel_pwmc_stop_sync(struct pwm_device *p)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ int was_on = __atmel_pwmc_is_on(p);
+ int chan = p - &ap->p[0];
+ int ret;
+
+ if (!was_on)
+ return 0;
+
+ do {
+ init_completion(&ap->complete);
+ set_bit(FLAG_STOP, &p->flags);
+ pwmc_writel(ap, PWMC_IER, BIT(chan));
+
+ dev_dbg(p->dev, "waiting on stop_sync completion...\n");
+
+ ret = wait_for_completion_interruptible(&ap->complete);
+
+ dev_dbg(p->dev, "stop_sync complete (%d)\n", ret);
+
+ if (ret)
+ return ret;
+ } while (test_bit(FLAG_STOP, &p->flags));
+
+ return 1;
+}
+
+static int atmel_pwmc_config(struct pwm_device *p, struct pwm_config *c)
+{
+ int was_on = 0;
+
+ if (p->ops->config_nosleep) {
+ if (!p->ops->config_nosleep(p, c))
+ return 0;
+ }
+
+ might_sleep();
+
+ dev_dbg(p->dev, "config_mask %lx\n", c->config_mask);
+
+ was_on = atmel_pwmc_stop_sync(p);
+ if (was_on < 0)
+ return was_on;
+
+ if (test_bit(PWM_CONFIG_PERIOD_TICKS, &c->config_mask)) {
+ __atmel_pwmc_config_period_ticks(p, c);
+ if (!test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask)) {
+ struct pwm_config d = {
+ .config_mask = PWM_CONFIG_DUTY_TICKS,
+ .duty_ticks = p->duty_ticks,
+ };
+ __atmel_pwmc_config_duty_ticks(p, &d);
+ }
+ }
+
+ if (test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask))
+ __atmel_pwmc_config_duty_ticks(p, c);
+
+ if (test_bit(PWM_CONFIG_POLARITY, &c->config_mask))
+ __atmel_pwmc_config_polarity(p, c);
+
+ if (test_bit(PWM_CONFIG_START, &c->config_mask)
+ || (was_on && !test_bit(PWM_CONFIG_STOP, &c->config_mask)))
+ __atmel_pwmc_start(p);
+
+ return 0;
+}
+
+static int atmel_pwmc_request(struct pwm_device *p)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ap->lock, flags);
+ clk_enable(ap->clk);
+ p->tick_hz = clk_get_rate(ap->clk);
+ __atmel_pwmc_stop(p);
+ spin_unlock_irqrestore(&ap->lock, flags);
+
+ return 0;
+}
+
+static void atmel_pwmc_release(struct pwm_device *p)
+{
+ struct atmel_pwmc *ap = pwm_get_drvdata(p);
+ clk_disable(ap->clk);
+}
+
+static irqreturn_t atmel_pwmc_irq(int irq, void *data)
+{
+ struct atmel_pwmc *ap = data;
+ struct pwm_device *p;
+ u32 isr;
+ int chan;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ap->lock, flags);
+
+ isr = pwmc_readl(ap, PWMC_ISR);
+ for (chan = 0; isr; chan++, isr >>= 1) {
+ p = &ap->p[chan];
+ if (isr & 1) {
+ pwm_callback(p);
+ if (test_bit(FLAG_STOP, &p->flags)) {
+ __atmel_pwmc_stop(p);
+ clear_bit(FLAG_STOP, &p->flags);
+ }
+ complete_all(&ap->complete);
+ }
+ }
+
+ spin_unlock_irqrestore(&ap->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit atmel_pwmc_probe(struct platform_device *pdev)
+{
+ struct atmel_pwmc *ap;
+ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int chan;
+ int ret = 0;
+
+ ap = kzalloc(sizeof *ap, GFP_KERNEL);
+ if (!ap) {
+ ret = -ENOMEM;
+ goto err_atmel_pwmc_alloc;
+ }
+
+ spin_lock_init(&ap->lock);
+ init_completion(&ap->complete);
+ platform_set_drvdata(pdev, ap);
+
+ /* TODO: the datasheets are unclear as to how large CCNT
+ * actually is across all adopters of the PWMC; sixteen bits
+ * seems a safe assumption for now */
+ ap->ccnt_mask = 0xffffUL;
+
+ ap->ops.request = atmel_pwmc_request;
+ ap->ops.release = atmel_pwmc_release;
+ ap->ops.config_nosleep = atmel_pwmc_config_nosleep;
+ ap->ops.config = atmel_pwmc_config;
+
+ ap->clk = clk_get(&pdev->dev, "pwm_clk");
+ if (IS_ERR(ap->clk)) {
+ ret = -ENODEV;
+ goto err_clk_get;
+ }
+
+ ap->iobase = ioremap_nocache(r->start, resource_size(r));
+ if (!ap->iobase) {
+ ret = -ENODEV;
+ goto err_ioremap;
+ }
+
+ clk_enable(ap->clk);
+ pwmc_writel(ap, PWMC_DIS, -1);
+ pwmc_writel(ap, PWMC_IDR, -1);
+ clk_disable(ap->clk);
+
+ for (chan = 0; chan < NCHAN; chan++) {
+ ap->p[chan].ops = &ap->ops;
+ pwm_set_drvdata(&ap->p[chan], ap);
+ ret = pwm_register(&ap->p[chan], &pdev->dev, chan);
+ if (ret)
+ goto err_pwm_register;
+ }
+
+ ap->irq = platform_get_irq(pdev, 0);
+ if (ap->irq != -ENXIO) {
+ ret = request_irq(ap->irq, atmel_pwmc_irq, 0,
+ dev_name(&pdev->dev), ap);
+ if (ret)
+ goto err_request_irq;
+ }
+
+ return 0;
+
+err_request_irq:
+err_pwm_register:
+ while (--chan > 0)
+ pwm_unregister(&ap->p[chan]);
+
+ iounmap(ap->iobase);
+err_ioremap:
+ clk_put(ap->clk);
+err_clk_get:
+ platform_set_drvdata(pdev, NULL);
+ kfree(ap);
+err_atmel_pwmc_alloc:
+ dev_dbg(&pdev->dev, "%s: error, returning %d\n", __func__, ret);
+ return ret;
+}
+
+static int __devexit atmel_pwmc_remove(struct platform_device *pdev)
+{
+ struct atmel_pwmc *ap = platform_get_drvdata(pdev);
+ int chan;
+
+ for (chan = 0; chan < NCHAN; chan++)
+ pwm_unregister(&ap->p[chan]);
+
+ clk_enable(ap->clk);
+ pwmc_writel(ap, PWMC_IDR, -1);
+ pwmc_writel(ap, PWMC_DIS, -1);
+ clk_disable(ap->clk);
+
+ if (ap->irq != -ENXIO)
+ free_irq(ap->irq, ap);
+
+ clk_put(ap->clk);
+ iounmap(ap->iobase);
+
+ kfree(ap);
+
+ return 0;
+}
+
+static struct platform_driver atmel_pwmc_driver = {
+ .driver = {
+ /* note: this name has to match the one in at91*_devices.c */
+ .name = "atmel_pwmc",
+ .owner = THIS_MODULE,
+ },
+ .probe = atmel_pwmc_probe,
+ .remove = __devexit_p(atmel_pwmc_remove),
+};
+
+static int __init atmel_pwmc_init(void)
+{
+ return platform_driver_register(&atmel_pwmc_driver);
+}
+module_init(atmel_pwmc_init);
+
+static void __exit atmel_pwmc_exit(void)
+{
+ platform_driver_unregister(&atmel_pwmc_driver);
+}
+module_exit(atmel_pwmc_exit);
+
+MODULE_AUTHOR("Bill Gatliff <bgat@billgatliff.com>");
+MODULE_DESCRIPTION("Driver for Atmel PWMC peripheral");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:atmel_pwmc");
--
1.7.2.3
^ permalink raw reply related
* [PWM v6 2/3] PWM: GPIO+hrtimer device emulation
From: Bill Gatliff @ 2011-02-21 3:35 UTC (permalink / raw)
To: linux-embedded; +Cc: Bill Gatliff
In-Reply-To: <1298259345-9794-1-git-send-email-bgat@billgatliff.com>
Emulates a PWM device using a GPIO pin and an hrtimer. Subject
to CPU, scheduler and hardware limitations, can support many
PWM outputs, e.g. as many as you have GPIO pins available for.
On a 200 MHz ARM9 processor, a PWM frequency of 100 Hz can be attained
with this code so long as the duty cycle remains between about 20-80%.
At higher or lower duty cycles, the transition events may arrive too
close for the scheduler and CPU to reliably service.
This driver supports creation of new GPIO+hrtimer PWM devices via
configfs:
# mount config /config -t configfs
# mkdir /config/gpio-pwm/<gpio number>
The new PWM device will appear as /sys/class/pwm/gpio-pwm.<gpio number>.
Caveats:
* The GPIO pin number must be valid, not already in use
* The output state of the GPIO pin is configured when the PWM starts
running i.e. not immediately upon request, because the polarity of
the inactive state of the pin isn't known until the pwm device's
'polarity' attribute is configured
* After creating and binding the pwm device, you must then request
it by reading from /sys/class/pwm/gpio-pwm.<gpio number>/request
Unbind and destroy the pwm device by first stopping and unrequesting
the pwm device under sysfs as usual; then do:
# rm -rf /config/gpio-pwm/<gpio number>
Signed-off-by: Bill Gatliff <bgat@billgatliff.com>
---
drivers/pwm/Kconfig | 11 ++
drivers/pwm/Makefile | 2 +
drivers/pwm/gpio-pwm.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 361 insertions(+), 0 deletions(-)
create mode 100644 drivers/pwm/gpio-pwm.c
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index bc550f7..476de67 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -8,3 +8,14 @@ menuconfig GENERIC_PWM
Enables PWM device support implemented via a generic
framework. If unsure, say N.
+config GPIO_PWM
+ tristate "GPIO+hrtimer PWM device emulation"
+ depends on GENERIC_PWM
+ help
+ When enabled, this feature emulates single-channel PWM
+ devices using high-resolution timers and GPIO pins. You may
+ create as many of these devices as desired, subject to CPU
+ throughput limitations and GPIO pin availability.
+
+ To compile this feature as a module, chose M here; the module
+ will be called gpio-pwm. If unsure, say N.
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 7baa201..ecec3e4 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -2,3 +2,5 @@
# Makefile for pwm devices
#
obj-$(CONFIG_GENERIC_PWM) := pwm.o
+
+obj-$(CONFIG_GPIO_PWM) += gpio-pwm.o
diff --git a/drivers/pwm/gpio-pwm.c b/drivers/pwm/gpio-pwm.c
new file mode 100644
index 0000000..39e2dc6
--- /dev/null
+++ b/drivers/pwm/gpio-pwm.c
@@ -0,0 +1,348 @@
+/*
+ * Emulates a PWM device using an hrtimer and GPIO pin
+ *
+ * Copyright (C) 2011 Bill Gatliff <bgat@billgatliff.com>
+ *
+ * This program is free software; you may redistribute and/or modify
+ * it under the terms of the GNU General Public License Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/configfs.h>
+#include <linux/pwm/pwm.h>
+
+#define DRIVER_NAME KBUILD_MODNAME
+
+struct gpio_pwm {
+ struct pwm_device pwm;
+ struct hrtimer t;
+ struct work_struct work;
+ spinlock_t lock;
+ struct completion complete;
+ int gpio;
+ int callback;
+ unsigned long polarity : 1;
+ unsigned long active : 1;
+ char name[16];
+};
+
+static inline struct gpio_pwm *to_gpio_pwm(const struct pwm_device *p)
+{
+ return container_of(p, struct gpio_pwm, pwm);
+}
+
+static void gpio_pwm_work(struct work_struct *work)
+{
+ struct gpio_pwm *gp = container_of(work, struct gpio_pwm, work);
+
+ gpio_direction_output(gp->gpio, !(!!gp->polarity ^ !!gp->active));
+}
+
+static enum hrtimer_restart gpio_pwm_timeout(struct hrtimer *t)
+{
+ struct gpio_pwm *gp = container_of(t, struct gpio_pwm, t);
+ struct pwm_device *p = &gp->pwm;
+
+ if (unlikely(p->duty_ticks == 0))
+ gp->active = 0;
+ else if (unlikely(p->duty_ticks == p->period_ticks))
+ gp->active = 1;
+ else
+ gp->active ^= 1;
+
+ if (gpio_cansleep(gp->gpio))
+ schedule_work(&gp->work);
+ else
+ gpio_pwm_work(&gp->work);
+
+ if (!gp->active && gp->callback)
+ pwm_callback(p);
+
+ if (unlikely(!gp->active && test_bit(FLAG_STOP, &p->flags))) {
+ clear_bit(FLAG_STOP, &p->flags);
+ complete_all(&gp->complete);
+ goto done;
+ }
+
+ if (gp->active)
+ hrtimer_forward_now(&gp->t, ktime_set(0, p->duty_ticks));
+ else
+ hrtimer_forward_now(&gp->t, ktime_set(0, p->period_ticks
+ - p->duty_ticks));
+
+done:
+ return HRTIMER_RESTART;
+}
+
+static void gpio_pwm_start(struct pwm_device *p)
+{
+ struct gpio_pwm *gp = to_gpio_pwm(p);
+
+ gp->active = 0;
+ hrtimer_start(&gp->t, ktime_set(0, p->period_ticks - p->duty_ticks),
+ HRTIMER_MODE_REL);
+ set_bit(FLAG_RUNNING, &p->flags);
+}
+
+static int gpio_pwm_config_nosleep(struct pwm_device *p, struct pwm_config *c)
+{
+ struct gpio_pwm *gp = to_gpio_pwm(p);
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gp->lock, flags);
+
+ switch (c->config_mask) {
+
+ case BIT(PWM_CONFIG_DUTY_TICKS):
+ p->duty_ticks = c->duty_ticks;
+ break;
+
+ case BIT(PWM_CONFIG_START):
+ if (!hrtimer_active(&gp->t)) {
+ gpio_pwm_start(p);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock_irqrestore(&gp->lock, flags);
+ return ret;
+}
+
+static int gpio_pwm_stop_sync(struct pwm_device *p)
+{
+ struct gpio_pwm *gp = to_gpio_pwm(p);
+ int ret;
+ int was_on = hrtimer_active(&gp->t);
+
+ if (was_on) {
+ do {
+ init_completion(&gp->complete);
+ set_bit(FLAG_STOP, &p->flags);
+ ret = wait_for_completion_interruptible(&gp->complete);
+ if (ret)
+ return ret;
+ } while (test_bit(FLAG_STOP, &p->flags));
+ }
+
+ clear_bit(FLAG_RUNNING, &p->flags);
+
+ return was_on;
+}
+
+static int gpio_pwm_config(struct pwm_device *p, struct pwm_config *c)
+{
+ struct gpio_pwm *gp = to_gpio_pwm(p);
+ int was_on = 0;
+
+ if (p->ops->config_nosleep) {
+ if (!p->ops->config_nosleep(p, c))
+ return 0;
+ }
+
+ might_sleep();
+
+ was_on = gpio_pwm_stop_sync(p);
+ if (was_on < 0)
+ return was_on;
+
+ if (test_bit(PWM_CONFIG_ENABLE_CALLBACK, &c->config_mask))
+ gp->callback = 1;
+ if (test_bit(PWM_CONFIG_DISABLE_CALLBACK, &c->config_mask))
+ gp->callback = 0;
+
+ if (test_bit(PWM_CONFIG_PERIOD_TICKS, &c->config_mask))
+ p->period_ticks = c->period_ticks;
+ if (test_bit(PWM_CONFIG_DUTY_TICKS, &c->config_mask))
+ p->duty_ticks = c->duty_ticks;
+ if (test_bit(PWM_CONFIG_POLARITY, &c->config_mask))
+ gp->polarity = !!c->polarity;
+
+ if (test_bit(PWM_CONFIG_START, &c->config_mask)
+ || (was_on && !test_bit(PWM_CONFIG_STOP, &c->config_mask)))
+ gpio_pwm_start(p);
+
+ return 0;
+}
+
+static int gpio_pwm_request(struct pwm_device *p)
+{
+ p->tick_hz = 1000000000UL;
+ return 0;
+}
+
+static const struct pwm_device_ops gpio_pwm_device_ops = {
+ .config = gpio_pwm_config,
+ .config_nosleep = gpio_pwm_config_nosleep,
+ .request = gpio_pwm_request,
+};
+
+struct pwm_device *gpio_pwm_create(int gpio)
+{
+ struct gpio_pwm *gp;
+ int ret = 0;
+
+ if (!gpio_is_valid(gpio))
+ return ERR_PTR(-EINVAL);
+
+ if (gpio_request(gpio, DRIVER_NAME))
+ return ERR_PTR(-EBUSY);
+
+ gp = kzalloc(sizeof(*gp), GFP_KERNEL);
+ if (!gp)
+ goto err_alloc;
+
+ pwm_set_drvdata(&gp->pwm, gp);
+ gp->pwm.ops = &gpio_pwm_device_ops;
+ gp->gpio = gpio;
+
+ INIT_WORK(&gp->work, gpio_pwm_work);
+ init_completion(&gp->complete);
+ hrtimer_init(&gp->t, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ gp->t.function = gpio_pwm_timeout;
+
+ scnprintf(gp->name, sizeof(gp->name), "%s:%d", DRIVER_NAME, gpio);
+ ret = pwm_register_byname(&gp->pwm, NULL, gp->name);
+ if (ret)
+ goto err_pwm_register;
+
+ return &gp->pwm;
+
+err_pwm_register:
+ kfree(gp);
+err_alloc:
+ gpio_free(gpio);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(gpio_pwm_create);
+
+int gpio_pwm_destroy(struct pwm_device *p)
+{
+ struct gpio_pwm *gp = pwm_get_drvdata(p);
+
+ if (pwm_is_requested(&gp->pwm)) {
+ if (pwm_is_running(&gp->pwm))
+ pwm_stop(&gp->pwm);
+ pwm_release(&gp->pwm);
+ }
+ hrtimer_cancel(&gp->t);
+ cancel_work_sync(&gp->work);
+
+ pwm_unregister(&gp->pwm);
+ gpio_free(gp->gpio);
+ kfree(gp);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_pwm_destroy);
+
+#ifdef CONFIG_CONFIGFS_FS
+struct gpio_pwm_target {
+ struct config_item item;
+ struct pwm_device *p;
+};
+
+static struct config_item_type gpio_pwm_item_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *make_gpio_pwm_target(struct config_group *group,
+ const char *name)
+{
+ struct gpio_pwm_target *t;
+ unsigned long gpio;
+ int ret;
+
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (!t)
+ return ERR_PTR(-ENOMEM);
+
+ ret = strict_strtoul(name, 10, &gpio);
+ if (ret || !gpio_is_valid(gpio)) {
+ ret = -EINVAL;
+ goto err_invalid_gpio;
+ }
+
+ config_item_init_type_name(&t->item, name, &gpio_pwm_item_type);
+
+ t->p = gpio_pwm_create(gpio);
+ if (IS_ERR_OR_NULL(t->p))
+ goto err_gpio_pwm_create;
+
+ return &t->item;
+
+err_gpio_pwm_create:
+err_invalid_gpio:
+ kfree(t);
+ return ERR_PTR(ret);
+}
+
+static void drop_gpio_pwm_target(struct config_group *group,
+ struct config_item *item)
+{
+ struct gpio_pwm_target *t =
+ container_of(item, struct gpio_pwm_target, item);
+
+ gpio_pwm_destroy(t->p);
+ config_item_put(&t->item);
+ kfree(t);
+}
+
+static struct configfs_group_operations gpio_pwm_subsys_group_ops = {
+ .make_item = make_gpio_pwm_target,
+ .drop_item = drop_gpio_pwm_target,
+};
+
+static struct config_item_type gpio_pwm_subsys_type = {
+ .ct_group_ops = &gpio_pwm_subsys_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem gpio_pwm_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_name = DRIVER_NAME,
+ .ci_type = &gpio_pwm_subsys_type,
+ },
+ },
+};
+
+static int __init gpio_pwm_init(void)
+{
+ config_group_init(&gpio_pwm_subsys.su_group);
+ mutex_init(&gpio_pwm_subsys.su_mutex);
+ return configfs_register_subsystem(&gpio_pwm_subsys);
+}
+module_init(gpio_pwm_init);
+
+static void __exit gpio_pwm_exit(void)
+{
+ configfs_unregister_subsystem(&gpio_pwm_subsys);
+}
+module_exit(gpio_pwm_exit);
+#endif
+
+MODULE_AUTHOR("Bill Gatliff <bgat@billgatliff.com>");
+MODULE_DESCRIPTION("PWM channel emulator using GPIO and a high-resolution timer");
+MODULE_LICENSE("GPL");
--
1.7.2.3
^ permalink raw reply related
* [PWM v6 1/3] PWM: Implement a generic PWM framework
From: Bill Gatliff @ 2011-02-21 3:35 UTC (permalink / raw)
To: linux-embedded; +Cc: Bill Gatliff
In-Reply-To: <1298259345-9794-1-git-send-email-bgat@billgatliff.com>
Updates the existing PWM-related functions to support multiple
and/or hotplugged PWM devices, and adds a sysfs interface.
Moves the code to drivers/pwm.
For now, this new code can exist alongside the current PWM
implementations; the existing implementations will be migrated
to this new framework as time permits. Eventually, the current
PWM implementation will be deprecated and then expunged.
Signed-off-by: Bill Gatliff <bgat@billgatliff.com>
---
Documentation/pwm.txt | 277 +++++++++++++++++++++
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/pwm/Kconfig | 10 +
drivers/pwm/Makefile | 4 +
drivers/pwm/pwm.c | 610 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pwm/pwm.h | 155 ++++++++++++
7 files changed, 1060 insertions(+), 0 deletions(-)
create mode 100644 Documentation/pwm.txt
create mode 100644 drivers/pwm/Kconfig
create mode 100644 drivers/pwm/Makefile
create mode 100644 drivers/pwm/pwm.c
create mode 100644 include/linux/pwm/pwm.h
diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
new file mode 100644
index 0000000..2b15395
--- /dev/null
+++ b/Documentation/pwm.txt
@@ -0,0 +1,277 @@
+ Generic PWM Device API
+
+ February 7, 2011
+ Bill Gatliff
+ <bgat@billgatliff.com>
+
+
+
+The code in drivers/pwm and include/linux/pwm/ implements an API for
+applications involving pulse-width-modulation signals. This document
+describes how the API implementation facilitates both PWM-generating
+devices, and users of those devices.
+
+
+
+Motivation
+
+The primary goals for implementing the "generic PWM API" are to
+consolidate the various PWM implementations within a consistent and
+redundancy-reducing framework, and to facilitate the use of
+hotpluggable PWM devices.
+
+Previous PWM-related implementations within the Linux kernel achieved
+their consistency via cut-and-paste, but did not need to (and didn't)
+facilitate more than one PWM-generating device within the system---
+hotplug or otherwise. The Generic PWM Device API might be most
+appropriately viewed as an update to those implementations, rather
+than a complete rewrite.
+
+
+
+Challenges
+
+One of the difficulties in implementing a generic PWM framework is the
+fact that pulse-width-modulation applications involve real-world
+signals, which often must be carefully managed to prevent destruction
+of hardware that is linked to those signals. A DC motor that
+experiences a brief interruption in the PWM signal controlling it
+might destructively overheat; it could suddenly change speed, losing
+synchronization with a sensor; it could even suddenly change direction
+or torque, breaking the mechanical device connected to it.
+
+(A generic PWM device framework is not directly responsible for
+preventing the above scenarios: that responsibility lies with the
+hardware designer, and the application and driver authors. But it
+must to the greatest extent possible make it easy to avoid such
+problems).
+
+A generic PWM device framework must accommodate the substantial
+differences between available PWM-generating hardware devices, without
+becoming sub-optimal for any of them.
+
+Finally, a generic PWM device framework must be relatively
+lightweight, computationally speaking. Some PWM users demand
+high-speed outputs, plus the ability to regulate those outputs
+quickly. A device framework must be able to "keep up" with such
+hardware, while still leaving time to do real work.
+
+The Generic PWM Device API is an attempt to meet all of the above
+requirements. At its initial publication, the API was already in use
+managing small DC motors, sensors and solenoids through a
+custom-designed, optically-isolated H-bridge driver.
+
+
+
+Functional Overview
+
+The Generic PWM Device API framework is implemented in
+include/linux/pwm/pwm.h and drivers/pwm/pwm.c. The functions therein
+use information from pwm_device and pwm__config structures to invoke
+services in PWM peripheral device drivers. Consult
+drivers/pwm/atmel-pwmc.c for an example driver for the Atmel PWMC
+peripheral.
+
+There are two classes of adopters of the PWM framework:
+
+ Users -- those wishing to employ the API merely to produce PWM
+ signals; once they have identified the appropriate physical output
+ on the platform in question, they don't care about the details of
+ the underlying hardware
+
+ Driver authors -- those wishing to bind devices that can generate
+ PWM signals to the Generic PWM Device API, so that the services of
+ those devices become available to users. Assuming the hardware can
+ support the needs of a user, driver authors don't care about the
+ details of the user's application
+
+Generally speaking, users will first invoke pwm_request() to obtain a
+handle to a PWM device. They will then pass that handle to functions
+like pwm_duty_ns() and pwm_period_ns() to set the duty cycle and
+period of the PWM signal, respectively. They will also invoke
+pwm_start() and pwm_stop() to turn the signal on and off.
+
+The Generic PWM API framework also provides a sysfs interface to PWM
+devices, which is adequate for basic application needs and testing.
+
+Driver authors fill out a pwm_device structure, which describes the
+capabilities of the PWM hardware being utilized. They then invoke
+pwm_register() (usually from within their device's probe() handler) to
+make the PWM API aware of their device. The framework will call back
+to the methods described in the pwm_device structure as users begin to
+configure and utilize the hardware.
+
+Many PWM-capable peripherals provide two, three, or more channels of
+PWM output. The driver author completes and registers a pwm_device
+structure for each channel they wish to be supported by the Generic
+PWM API.
+
+Note that PWM signals can be produced by a variety of peripherals,
+beyond the true PWM peripherals offered by many system-on-chip
+devices. Other possibilities include timer/counters with
+compare-match capabilities, carefully-programmed synchronous serial
+ports (e.g. SPI), and GPIO pins driven by kernel interval timers.
+With a proper pwm_device structure, these devices and pseudo-devices
+can be accommodated by the Generic PWM Device API framework.
+
+
+
+Using the API to Generate PWM Signals -- Basic Functions for Users
+
+
+pwm_request() -- Returns a pwm_device pointer, which is subsequently
+passed to the other user-related PWM functions. Once requested, a PWM
+channel is marked as in-use and subsequent requests prior to
+pwm_release() will fail.
+
+The names used to refer to PWM devices are defined by driver authors.
+Typically they are platform device bus identifiers, and this
+convention is encouraged for consistency.
+
+
+pwm_release() -- Marks a PWM channel as no longer in use. The PWM
+device is stopped before it is released by the API.
+
+
+pwm_period_ns() -- Specifies the PWM signal's period, in nanoseconds.
+
+
+pwm_duty_ns() -- Specifies the PWM signal's active duration, in nanoseconds.
+
+
+pwm_duty_percent() -- Specifies the PWM signal's active duration, as a
+percentage of the current period of the signal. NOTE: this value is
+not recalculated if the period of the signal is subsequently changed.
+
+
+pwm_start(), pwm_stop() -- Turns the PWM signal on and off. Except
+where stated otherwise by a driver author, signals are stopped at the
+end of the current period, at which time the output is set to its
+inactive state.
+
+
+pwm_polarity() -- Defines whether the PWM signal output's active
+region is "1" or "0". A 10% duty-cycle, polarity=1 signal will
+conventionally be at 5V (or 3.3V, or 1000V, or whatever the platform
+hardware does) for 10% of the period. The same configuration of a
+polarity=0 signal will be at 5V (or 3.3V, or ...) for 90% of the
+period.
+
+
+
+Using the API to Generate PWM Signals -- Advanced Functions
+
+
+pwm_config() -- Passes a pwm_config structure to the associated device
+driver. This function is invoked by pwm_start(), pwm_duty_ns(),
+etc. and is one of two main entry points to the PWM driver for the
+hardware being used. The configuration change is guaranteed atomic if
+multiple configuration changes are specified by the config structure.
+This function might sleep, depending on what the device driver has to
+do to satisfy the request. All PWM device drivers must support this
+entry point.
+
+
+pwm_config_nosleep() -- Passes a pwm_config structure to the
+associated device driver. If the driver must sleep in order to
+implement the requested configuration change, -EWOULDBLOCK is
+returned. Users may call this function from interrupt handlers, timer
+handlers, and other interrupt contexts, but must confine their
+configuration changes to only those that the driver can implement
+without sleeping. This is the other main entry point into the PWM
+hardware driver, but not all device drivers support this entry point.
+
+
+pwm_synchronize(), pwm_unsynchronize() -- "Synchronizes" two or more
+PWM channels, if the underlying hardware permits. (If it doesn't, the
+framework facilitates emulating this capability but it is not yet
+implemented). Synchronized channels will start and stop
+simultaneously when any single channel in the group is started or
+stopped. Use pwm_unsynchronize(..., NULL) to completely detach a
+channel from any other synchronized channels. By default, all PWM
+channels are unsynchronized.
+
+
+pwm_set_handler() -- Defines an end-of-period callback. The indicated
+function will be invoked in a worker thread at the end of each PWM
+period, and can subsequently invoke pwm_config(), etc. Must be used
+with extreme care for high-speed PWM outputs. Set the handler
+function to NULL to un-set the handler.
+
+
+
+Implementing a PWM Device API Driver -- Functions for Driver Authors
+
+
+Fill out the appropriate fields in a pwm_device structure, and submit
+to pwm_register():
+
+
+bus_id -- the plain-text name of the device. Users will bind to a
+channel on the device using this name plus the channel number. For
+example, the Atmel PWMC's bus_id is "atmel_pwmc", the same as used by
+the platform device driver (recommended). The first Atmel PWMC
+platform device registered thereby receives bus_id "atmel_pwmc.0",
+which is what you put in pwm_device.bus_id. Channels are then named
+"atmel_pwmc.0:[0-3]". (Hint: just use dev_name(pdev->dev) in your
+probe() method).
+
+
+request -- (optional) Invoked each time a user requests a channel.
+Use to turn on clocks, clean up register states, etc. The framework
+takes care of device locking/unlocking; you will see only successful
+requests.
+
+
+free -- (optional) Invoked each time a user relinquishes a channel.
+The framework will have already stopped, unsynchronized and un-handled
+the channel. Use to turn off clocks, etc. as necessary.
+
+
+set_callback -- (optional) If the hardware supports an end-of-period
+interrupt, invoke the function provided in this callback during the
+device's interrupt handler. The callback function itself is always
+internal to the API, and does not map directly to the user's callback
+function.
+
+
+config -- Invoked to change the device configuration, always from a
+sleep-compatible context. All the changes indicated must be performed
+atomically, ideally synchronized to an end-of-period event (so that
+you avoid short or long output pulses). You may sleep, etc. as
+necessary within this function.
+
+
+config_nosleep -- (optional) Invoked to change device configuration
+from within a context that is not allowed to sleep. If you cannot
+perform the requested configuration changes without sleeping, return
+-EWOULDBLOCK.
+
+
+
+FAQs and Additional Notes
+
+The Atmel PWMC pwm_config() function tries to satisfy the user's
+configuration request by first invoking pwm_config_nosleep(). If that
+operation fails, then the PWM peripheral is brought to a synchronized
+stop, the configuration changes are made, and the device is restarted.
+
+The Atmel PWMC's use of pwm_config_nosleep() from pwm_config()
+minimizes redundant code between the two functions, and relieves the
+pwm_config() function of the need to explicitly test whether a
+requested configuration change can be carried out while the PWM device
+is in its current mode.
+
+PWM API driver authors are encouraged to adopt the Atmel PWMC's
+pwm_config()-vs.-pwm_config_nosleep() strategy in implementations for
+other devices as well.
+
+
+
+Acknowledgements
+
+
+The author expresses his gratitude to the countless developers who
+have reviewed and submitted feedback on the various versions of the
+Generic PWM Device API code, and those who have submitted drivers and
+applications that use the framework. You know who you are. ;)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9bfb71f..413e4f9 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,8 @@ source "drivers/pps/Kconfig"
source "drivers/gpio/Kconfig"
+source "drivers/pwm/Kconfig"
+
source "drivers/w1/Kconfig"
source "drivers/power/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index b423bb1..4e37abf 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -6,6 +6,8 @@
#
obj-y += gpio/
+obj-$(CONFIG_GENERIC_PWM) += pwm/
+
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
new file mode 100644
index 0000000..bc550f7
--- /dev/null
+++ b/drivers/pwm/Kconfig
@@ -0,0 +1,10 @@
+#
+# PWM infrastructure and devices
+#
+
+menuconfig GENERIC_PWM
+ tristate "PWM Support"
+ help
+ Enables PWM device support implemented via a generic
+ framework. If unsure, say N.
+
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
new file mode 100644
index 0000000..7baa201
--- /dev/null
+++ b/drivers/pwm/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for pwm devices
+#
+obj-$(CONFIG_GENERIC_PWM) := pwm.o
diff --git a/drivers/pwm/pwm.c b/drivers/pwm/pwm.c
new file mode 100644
index 0000000..f958e4b
--- /dev/null
+++ b/drivers/pwm/pwm.c
@@ -0,0 +1,610 @@
+/*
+ * PWM API implementation
+ *
+ * Copyright (C) 2011 Bill Gatliff <bgat@billgatliff.com>
+ * Copyright (C) 2011 Arun Murthy <arun.murthy@stericsson.com>
+ *
+ * This program is free software; you may redistribute and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/pwm/pwm.h>
+
+static const char *REQUEST_SYSFS = "sysfs";
+static LIST_HEAD(pwm_device_list);
+static DEFINE_MUTEX(device_list_mutex);
+static struct class pwm_class;
+static struct workqueue_struct *pwm_handler_workqueue;
+
+static int pwm_match_name(struct device *dev, void *name)
+{
+ return !strcmp(name, dev_name(dev));
+}
+
+static int __pwm_request(struct pwm_device *p, const char *label)
+{
+ int ret;
+
+ ret = test_and_set_bit(FLAG_REQUESTED, &p->flags);
+ if (ret) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ p->label = label;
+
+ if (p->ops->request) {
+ ret = p->ops->request(p);
+ if (ret) {
+ clear_bit(FLAG_REQUESTED, &p->flags);
+ goto done;
+ }
+ }
+
+done:
+ return ret;
+}
+
+static struct pwm_device *__pwm_request_byname(const char *name,
+ const char *label)
+{
+ struct device *d;
+ struct pwm_device *p;
+ int ret;
+
+ d = class_find_device(&pwm_class, NULL, (char*)name, pwm_match_name);
+ if (IS_ERR_OR_NULL(d))
+ return ERR_PTR(-EINVAL);
+
+ p = dev_get_drvdata(d);
+ ret = __pwm_request(p, label);
+
+ if (ret)
+ return ERR_PTR(ret);
+ return p;
+}
+
+struct pwm_device *pwm_request_byname(const char *name, const char *label)
+{
+ struct pwm_device *p;
+
+ mutex_lock(&device_list_mutex);
+ p = __pwm_request_byname(name, label);
+ mutex_unlock(&device_list_mutex);
+ return p;
+}
+EXPORT_SYMBOL(pwm_request_byname);
+
+struct pwm_device *pwm_request(const char *bus_id, int id, const char *label)
+{
+ char name[256];
+ int ret;
+
+ if (id == -1)
+ ret = scnprintf(name, sizeof name, "%s", bus_id);
+ else
+ ret = scnprintf(name, sizeof name, "%s:%d", bus_id, id);
+ if (ret <= 0 || ret >= sizeof name)
+ return ERR_PTR(-EINVAL);
+
+ return pwm_request_byname(name, label);
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_release(struct pwm_device *p)
+{
+ mutex_lock(&device_list_mutex);
+
+ if (!test_and_clear_bit(FLAG_REQUESTED, &p->flags)) {
+ WARN(1, "%s: releasing unrequested PWM device %s\n",
+ __func__, dev_name(p->dev));
+ goto done;
+ }
+
+ pwm_stop(p);
+ pwm_unsynchronize(p, NULL);
+ pwm_set_handler(p, NULL, NULL);
+
+ p->label = NULL;
+
+ if (p->ops->release)
+ p->ops->release(p);
+done:
+ mutex_unlock(&device_list_mutex);
+}
+EXPORT_SYMBOL(pwm_release);
+
+static unsigned long pwm_ns_to_ticks(struct pwm_device *p, unsigned long nsecs)
+{
+ unsigned long long ticks;
+
+ ticks = nsecs;
+ ticks *= p->tick_hz;
+ do_div(ticks, 1000000000);
+ return ticks;
+}
+
+static unsigned long pwm_ticks_to_ns(struct pwm_device *p, unsigned long ticks)
+{
+ unsigned long long ns;
+
+ if (!p->tick_hz)
+ return 0;
+
+ ns = ticks;
+ ns *= 1000000000UL;
+ do_div(ns, p->tick_hz);
+ return ns;
+}
+
+int pwm_config_nosleep(struct pwm_device *p, struct pwm_config *c)
+{
+ if (!p->ops->config_nosleep)
+ return -EINVAL;
+
+ return p->ops->config_nosleep(p, c);
+}
+EXPORT_SYMBOL(pwm_config_nosleep);
+
+int pwm_config(struct pwm_device *p, struct pwm_config *c)
+{
+ int ret = 0;
+
+ switch (c->config_mask & (BIT(PWM_CONFIG_PERIOD_TICKS)
+ | BIT(PWM_CONFIG_DUTY_TICKS))) {
+ case BIT(PWM_CONFIG_PERIOD_TICKS):
+ if (p->duty_ticks > c->period_ticks) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ case BIT(PWM_CONFIG_DUTY_TICKS):
+ if (p->period_ticks < c->duty_ticks) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ case BIT(PWM_CONFIG_DUTY_TICKS) | BIT(PWM_CONFIG_PERIOD_TICKS):
+ if (c->duty_ticks > c->period_ticks) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ default:
+ break;
+ }
+
+err:
+ dev_dbg(p->dev, "%s: config_mask %lu period_ticks %lu "
+ "duty_ticks %lu polarity %d\n",
+ __func__, c->config_mask, c->period_ticks,
+ c->duty_ticks, c->polarity);
+
+ if (ret)
+ return ret;
+ return p->ops->config(p, c);
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_set(struct pwm_device *p, unsigned long period_ns,
+ unsigned long duty_ns, int active_high)
+{
+ struct pwm_config c = {
+ .config_mask = (BIT(PWM_CONFIG_PERIOD_TICKS)
+ | BIT(PWM_CONFIG_DUTY_TICKS)
+ | BIT(PWM_CONFIG_POLARITY)),
+ .period_ticks = pwm_ns_to_ticks(p, period_ns),
+ .duty_ticks = pwm_ns_to_ticks(p, duty_ns),
+ .polarity = active_high
+ };
+
+ return pwm_config(p, &c);
+}
+EXPORT_SYMBOL(pwm_set);
+
+int pwm_set_period_ns(struct pwm_device *p, unsigned long period_ns)
+{
+ struct pwm_config c = {
+ .config_mask = BIT(PWM_CONFIG_PERIOD_TICKS),
+ .period_ticks = pwm_ns_to_ticks(p, period_ns),
+ };
+
+ return pwm_config(p, &c);
+}
+EXPORT_SYMBOL(pwm_set_period_ns);
+
+unsigned long pwm_get_period_ns(struct pwm_device *p)
+{
+ return pwm_ticks_to_ns(p, p->period_ticks);
+}
+EXPORT_SYMBOL(pwm_get_period_ns);
+
+int pwm_set_duty_ns(struct pwm_device *p, unsigned long duty_ns)
+{
+ struct pwm_config c = {
+ .config_mask = BIT(PWM_CONFIG_DUTY_TICKS),
+ .duty_ticks = pwm_ns_to_ticks(p, duty_ns),
+ };
+ return pwm_config(p, &c);
+}
+EXPORT_SYMBOL(pwm_set_duty_ns);
+
+unsigned long pwm_get_duty_ns(struct pwm_device *p)
+{
+ return pwm_ticks_to_ns(p, p->duty_ticks);
+}
+EXPORT_SYMBOL(pwm_get_duty_ns);
+
+int pwm_set_polarity(struct pwm_device *p, int active_high)
+{
+ struct pwm_config c = {
+ .config_mask = BIT(PWM_CONFIG_POLARITY),
+ .polarity = active_high,
+ };
+ return pwm_config(p, &c);
+}
+EXPORT_SYMBOL(pwm_set_polarity);
+
+int pwm_start(struct pwm_device *p)
+{
+ struct pwm_config c = {
+ .config_mask = BIT(PWM_CONFIG_START),
+ };
+ return pwm_config(p, &c);
+}
+EXPORT_SYMBOL(pwm_start);
+
+int pwm_stop(struct pwm_device *p)
+{
+ struct pwm_config c = {
+ .config_mask = BIT(PWM_CONFIG_STOP),
+ };
+ return pwm_config(p, &c);
+}
+EXPORT_SYMBOL(pwm_stop);
+
+int pwm_synchronize(struct pwm_device *p, struct pwm_device *to_p)
+{
+ if (!p->ops->synchronize)
+ return -EINVAL;
+
+ return p->ops->synchronize(p, to_p);
+}
+EXPORT_SYMBOL(pwm_synchronize);
+
+int pwm_unsynchronize(struct pwm_device *p, struct pwm_device *from_p)
+{
+ if (!p->ops->unsynchronize)
+ return -EINVAL;
+
+ return p->ops->unsynchronize(p, from_p);
+}
+EXPORT_SYMBOL(pwm_unsynchronize);
+
+static void pwm_handler(struct work_struct *w)
+{
+ struct pwm_device *p = container_of(w, struct pwm_device,
+ handler_work);
+ if (p->handler)
+ p->handler(p, p->handler_data);
+}
+
+void pwm_callback(struct pwm_device *p)
+{
+ queue_work(pwm_handler_workqueue, &p->handler_work);
+}
+EXPORT_SYMBOL(pwm_callback);
+
+int pwm_set_handler(struct pwm_device *p, pwm_handler_t handler, void *data)
+{
+ struct pwm_config c;
+ int ret;
+
+ if (handler)
+ c.config_mask = BIT(PWM_CONFIG_ENABLE_CALLBACK);
+ else
+ c.config_mask = BIT(PWM_CONFIG_DISABLE_CALLBACK);
+
+ ret = pwm_config(p, &c);
+
+ if (!ret && handler) {
+ p->handler_data = data;
+ p->handler = handler;
+ INIT_WORK(&p->handler_work, pwm_handler);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(pwm_set_handler);
+
+static ssize_t pwm_run_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", pwm_is_running(p));
+}
+
+static ssize_t pwm_run_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+
+ if (!pwm_is_exported(p))
+ return -EINVAL;
+
+ if (sysfs_streq(buf, "1"))
+ pwm_start(p);
+ else if (sysfs_streq(buf, "0"))
+ pwm_stop(p);
+
+ return len;
+}
+static DEVICE_ATTR(run, S_IRUGO | S_IWUSR, pwm_run_show, pwm_run_store);
+
+static ssize_t pwm_tick_hz_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+ return sprintf(buf, "%lu\n", p->tick_hz);
+}
+static DEVICE_ATTR(tick_hz, S_IRUGO, pwm_tick_hz_show, NULL);
+
+static ssize_t pwm_duty_ns_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+ return sprintf(buf, "%lu\n", pwm_get_duty_ns(p));
+}
+
+static ssize_t pwm_duty_ns_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ unsigned long duty_ns;
+ struct pwm_device *p = dev_get_drvdata(dev);
+
+ if (!pwm_is_exported(p))
+ return -EINVAL;
+
+ if (!strict_strtoul(buf, 10, &duty_ns))
+ pwm_set_duty_ns(p, duty_ns);
+ return len;
+}
+static DEVICE_ATTR(duty_ns, S_IRUGO | S_IWUSR, pwm_duty_ns_show, pwm_duty_ns_store);
+
+static ssize_t pwm_period_ns_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+ return sprintf(buf, "%lu\n", pwm_get_period_ns(p));
+}
+
+static ssize_t pwm_period_ns_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ unsigned long period_ns;
+ struct pwm_device *p = dev_get_drvdata(dev);
+
+ if (!pwm_is_exported(p))
+ return -EINVAL;
+
+ if (!strict_strtoul(buf, 10, &period_ns))
+ pwm_set_period_ns(p, period_ns);
+ return len;
+}
+static DEVICE_ATTR(period_ns, S_IRUGO | S_IWUSR, pwm_period_ns_show, pwm_period_ns_store);
+
+static ssize_t pwm_polarity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", p->active_high ? 1 : 0);
+}
+
+static ssize_t pwm_polarity_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ unsigned long polarity;
+ struct pwm_device *p = dev_get_drvdata(dev);
+
+ if (!pwm_is_exported(p))
+ return -EINVAL;
+
+ if (!strict_strtoul(buf, 10, &polarity))
+ pwm_set_polarity(p, polarity);
+ return len;
+}
+static DEVICE_ATTR(polarity, S_IRUGO | S_IWUSR, pwm_polarity_show, pwm_polarity_store);
+
+static ssize_t pwm_request_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+ int ret;
+
+ mutex_lock(&device_list_mutex);
+ ret = __pwm_request(p, REQUEST_SYSFS);
+ mutex_unlock(&device_list_mutex);
+
+ if (!ret)
+ set_bit(FLAG_EXPORTED, &p->flags);
+
+ return sprintf(buf, "%s\n", p->label);
+}
+
+static ssize_t pwm_request_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pwm_device *p = dev_get_drvdata(dev);
+
+ pwm_release(p);
+ clear_bit(FLAG_EXPORTED, &p->flags);
+ return len;
+}
+static DEVICE_ATTR(request, S_IRUGO | S_IWUSR, pwm_request_show, pwm_request_store);
+
+static const struct attribute *pwm_attrs[] = {
+ &dev_attr_tick_hz.attr,
+ &dev_attr_run.attr,
+ &dev_attr_polarity.attr,
+ &dev_attr_duty_ns.attr,
+ &dev_attr_period_ns.attr,
+ &dev_attr_request.attr,
+ NULL,
+};
+
+static const struct attribute_group pwm_device_attr_group = {
+ .attrs = (struct attribute **) pwm_attrs,
+};
+
+static struct class_attribute pwm_class_attrs[] = {
+ __ATTR_NULL,
+};
+
+static struct class pwm_class = {
+ .name = "pwm",
+ .owner = THIS_MODULE,
+
+ .class_attrs = pwm_class_attrs,
+};
+
+int pwm_register_byname(struct pwm_device *p, struct device *parent,
+ const char *name)
+{
+ struct device *d;
+ int ret;
+
+ if (!p->ops || !p->ops->config)
+ return -EINVAL;
+
+ mutex_lock(&device_list_mutex);
+
+ d = class_find_device(&pwm_class, NULL, (char*)name, pwm_match_name);
+ if (d) {
+ ret = -EEXIST;
+ goto err_found_device;
+ }
+
+ p->dev = device_create(&pwm_class, parent, MKDEV(0, 0), NULL, name);
+ if (IS_ERR(p->dev)) {
+ ret = PTR_ERR(p->dev);
+ goto err_device_create;
+ }
+
+ ret = sysfs_create_group(&p->dev->kobj, &pwm_device_attr_group);
+ if (ret)
+ goto err_create_group;
+
+ dev_set_drvdata(p->dev, p);
+ p->flags = BIT(FLAG_REGISTERED);
+
+ goto done;
+
+err_create_group:
+ device_unregister(p->dev);
+ p->flags = 0;
+
+err_device_create:
+err_found_device:
+done:
+ mutex_unlock(&device_list_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(pwm_register_byname);
+
+int pwm_register(struct pwm_device *p, struct device *parent, int id)
+{
+ int ret;
+ char name[256];
+
+ if (IS_ERR_OR_NULL(parent))
+ return -EINVAL;
+
+ if (id == -1)
+ ret = scnprintf(name, sizeof name, "%s", dev_name(parent));
+ else
+ ret = scnprintf(name, sizeof name, "%s:%d", dev_name(parent), id);
+ if (ret <= 0 || ret >= sizeof name)
+ return -EINVAL;
+
+ return pwm_register_byname(p, parent, name);
+}
+EXPORT_SYMBOL(pwm_register);
+
+int pwm_unregister(struct pwm_device *p)
+{
+ int ret = 0;
+
+ mutex_lock(&device_list_mutex);
+
+ if (pwm_is_running(p) || pwm_is_requested(p)) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ sysfs_remove_group(&p->dev->kobj, &pwm_device_attr_group);
+ device_unregister(p->dev);
+ p->flags = 0;
+
+done:
+ mutex_unlock(&device_list_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(pwm_unregister);
+
+static int __init pwm_init(void)
+{
+ pwm_handler_workqueue = create_singlethread_workqueue("pwm");
+ if (IS_ERR_OR_NULL(pwm_handler_workqueue)) {
+ pr_err("%s: failed to create PWM workqueue; aborting\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ return class_register(&pwm_class);
+}
+
+static void __exit pwm_exit(void)
+{
+ destroy_workqueue(pwm_handler_workqueue);
+ class_unregister(&pwm_class);
+}
+
+postcore_initcall(pwm_init);
+module_exit(pwm_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bill Gatliff <bgat@billgatliff.com>");
+MODULE_DESCRIPTION("Generic PWM device API implementation");
diff --git a/include/linux/pwm/pwm.h b/include/linux/pwm/pwm.h
new file mode 100644
index 0000000..1447333
--- /dev/null
+++ b/include/linux/pwm/pwm.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011 Bill Gatliff < bgat@billgatliff.com>
+ * Copyright (C) 2011 Arun Murthy <arun.murth@stericsson.com>
+ *
+ * This program is free software; you may redistribute and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+#ifndef __LINUX_PWM_H
+#define __LINUX_PWM_H
+
+enum {
+ FLAG_REGISTERED = 0,
+ FLAG_REQUESTED = 1,
+ FLAG_STOP = 2,
+ FLAG_RUNNING = 3,
+ FLAG_EXPORTED = 4,
+};
+
+enum {
+ PWM_CONFIG_DUTY_TICKS = 0,
+ PWM_CONFIG_PERIOD_TICKS = 1,
+ PWM_CONFIG_POLARITY = 2,
+ PWM_CONFIG_START = 3,
+ PWM_CONFIG_STOP = 4,
+
+ PWM_CONFIG_ENABLE_CALLBACK = 9,
+ PWM_CONFIG_DISABLE_CALLBACK = 10,
+};
+
+struct pwm_config;
+struct pwm_device;
+
+typedef int (*pwm_handler_t)(struct pwm_device *p, void *data);
+typedef void (*pwm_callback_t)(struct pwm_device *p);
+
+struct pwm_device_ops {
+ int (*request) (struct pwm_device *p);
+ void (*release) (struct pwm_device *p);
+ int (*config) (struct pwm_device *p,
+ struct pwm_config *c);
+ int (*config_nosleep) (struct pwm_device *p,
+ struct pwm_config *c);
+ int (*synchronize) (struct pwm_device *p,
+ struct pwm_device *to_p);
+ int (*unsynchronize) (struct pwm_device *p,
+ struct pwm_device *from_p);
+};
+
+struct pwm_config {
+ unsigned long config_mask;
+
+ unsigned long duty_ticks;
+ unsigned long period_ticks;
+ int polarity;
+};
+
+struct pwm_device {
+ struct device *dev;
+ const struct pwm_device_ops *ops;
+
+ const void *data;
+
+ const char *label;
+
+ unsigned long flags;
+
+ unsigned long tick_hz;
+
+ struct work_struct handler_work;
+ pwm_handler_t handler;
+ void *handler_data;
+
+ int active_high;
+ unsigned long period_ticks;
+ unsigned long duty_ticks;
+};
+
+struct pwm_device *pwm_request_byname(const char *name, const char *label);
+struct pwm_device *pwm_request(const char *bus_id, int id, const char *label);
+void pwm_release(struct pwm_device *p);
+
+static inline int pwm_is_registered(const struct pwm_device *p)
+{
+ return test_bit(FLAG_REGISTERED, &p->flags);
+}
+
+static inline int pwm_is_requested(const struct pwm_device *p)
+{
+ return test_bit(FLAG_REQUESTED, &p->flags);
+}
+
+static inline int pwm_is_running(const struct pwm_device *p)
+{
+ return test_bit(FLAG_RUNNING, &p->flags);
+}
+
+static inline int pwm_is_exported(const struct pwm_device *p)
+{
+ return test_bit(FLAG_EXPORTED, &p->flags);
+}
+
+static inline void pwm_set_drvdata(struct pwm_device *p, const void *data)
+{
+ p->data = data;
+}
+
+static inline void *pwm_get_drvdata(const struct pwm_device *p)
+{
+ return (void*)p->data;
+}
+
+
+int pwm_register(struct pwm_device *p, struct device *parent, int id);
+int pwm_register_byname(struct pwm_device *p, struct device *parent,
+ const char *name);
+int pwm_unregister(struct pwm_device *p);
+
+int pwm_set(struct pwm_device *p, unsigned long period_ns,
+ unsigned long duty_ns, int active_high);
+
+int pwm_set_period_ns(struct pwm_device *p, unsigned long period_ns);
+unsigned long pwm_get_period_ns(struct pwm_device *p);
+
+int pwm_set_duty_ns(struct pwm_device *p, unsigned long duty_ns);
+unsigned long pwm_get_duty_ns(struct pwm_device *p);
+
+int pwm_set_polarity(struct pwm_device *p, int active_high);
+
+int pwm_start(struct pwm_device *p);
+int pwm_stop(struct pwm_device *p);
+
+int pwm_config_nosleep(struct pwm_device *p, struct pwm_config *c);
+int pwm_config(struct pwm_device *p, struct pwm_config *c);
+
+int pwm_synchronize(struct pwm_device *p, struct pwm_device *to_p);
+int pwm_unsynchronize(struct pwm_device *p, struct pwm_device *from_p);
+int pwm_set_handler(struct pwm_device *p, pwm_handler_t handler, void *data);
+
+void pwm_callback(struct pwm_device *p);
+
+struct pwm_device *gpio_pwm_create(int gpio);
+int gpio_pwm_destroy(struct pwm_device *p);
+
+#endif
--
1.7.2.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox