* Re: [RFCv1 03/11] Bluetooth: AMP: Process Physical Link Complete evt
From: Andrei Emeltchenko @ 2012-10-29 9:22 UTC (permalink / raw)
To: Mat Martineau; +Cc: linux-bluetooth
In-Reply-To: <alpine.DEB.2.02.1210261012440.2459@mathewm-linux>
Hi Mat,
On Fri, Oct 26, 2012 at 10:16:53AM -0700, Mat Martineau wrote:\
...
> >+static void hci_phy_link_complete_evt(struct hci_dev *hdev,
> >+ struct sk_buff *skb)
> >+{
> >+ struct hci_ev_phy_link_complete *ev = (void *) skb->data;
> >+ struct hci_conn *hcon, *bredr_hcon;
> >+
> >+ BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
> >+ ev->status);
> >+
> >+ hci_dev_lock(hdev);
> >+
> >+ hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
> >+ if (!hcon) {
> >+ hci_dev_unlock(hdev);
> >+ return;
> >+ }
> >+
> >+ if (ev->status) {
> >+ hci_conn_del(hcon);
> >+ hci_dev_unlock(hdev);
> >+ return;
> >+ }
> >+
> >+ bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
> >+
> >+ hcon->state = BT_CONNECTED;
> >+ bacpy(&hcon->dst, &bredr_hcon->dst);
> >+
> >+ hci_conn_hold(hcon);
> >+ hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
> >+ hci_conn_put(hcon);
> >+
> >+ hci_conn_hold_device(hcon);
> >+ hci_conn_add_sysfs(hcon);
> >+
> >+ hci_dev_unlock(hdev);
> >+
> >+ if (hcon->out) {
> >+ struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
> >+
> >+ if (!bredr_hdev)
> >+ return;
> >+
> >+ /* Placeholder - create chan req
> >+ l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id);
> >+ */
>
> I think this is where you would call l2cap_physical_cfm(), but that
> function requires more information. Is there enough context in hcon
> to get the local amp ID
This one is easy to manage: hcon->dev->id
> and l2cap_chan, or does the AMP manager need
> to be notified of the physical link so it can match up the physical
> link with other information?
I get chan from amp_mgr through hcon->amp_mgr
I will send the patch later this week.
Best regards
Andrei Emeltchenko
^ permalink raw reply
* Re: [PATCH v3 06/10] sbc: Add mmx primitive for 1b 8s analyse
From: Dalleau, Frederic @ 2012-10-29 7:42 UTC (permalink / raw)
To: Siarhei Siamashka; +Cc: Frédéric Dalleau, linux-bluetooth
In-Reply-To: <20121028022942.3bcd1bd7@i7>
Hi Siarhei,
Since only neon is concerned by this, I'd rather add a one liner like this :
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
sbc_init_primitives_neon(state);
+
+ if (state->increment == 1)
+ state->sbc_analyze_4b_8s = sbc_analyze_1b_8s_simd;
#endif
It is more explicit, doesn't change priority and doesn't add needless code
to other implementations.
And what about sbc_analyze_8s?
Regarding point 2, this is the reason why patch 4 was a bit bigger, the simd
implementation is complete.
Regards,
Frédéric
^ permalink raw reply
* Re: [PATCH v3 04/10] sbc: Add msbc flag and generic C primitive
From: Dalleau, Frederic @ 2012-10-29 6:47 UTC (permalink / raw)
To: Siarhei Siamashka; +Cc: Frédéric Dalleau, linux-bluetooth
In-Reply-To: <20121028011948.30f09efe@i7>
Hi Siarhei,
Thanks for review, I mostly agree but have a few remarks.
On Sun, Oct 28, 2012 at 12:19 AM, Siarhei Siamashka
<siarhei.siamashka@gmail.com> wrote:
> On Fri, 26 Oct 2012 19:20:30 +0200
> If "position" was not decremented by 16 for 8 samples here, then you
> would not need to do
> if (state->pending == state->position)
> x += 8;
> elsewhere.
Good idea, just note that in this case, one sample (x[1] = PCM(0 + 7
* nchannels))
will receive a negative index x[-7]. there is no technical problème
just a matter of style.
> One more nitpick about "sbc_encoder_process_input_s8". The old
> variant was taking "position" as a function argument and returning
> an updated position.
Addtionnally, sbc_encoder_process_input_s8 would return void, and
state->position
would be used directly from process_input function. However, it requires changes
in the neon code, which I'd rather avoid for now. I can send a patch
later for this one.
Regards,
Frédéric
^ permalink raw reply
* Re: BLE issue: Start_LE_Encryption fails
From: Ajay @ 2012-10-29 1:33 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_P=USyDO5op7_7ynOT8Qe7dOifyN=notezK1HGCxOe8bA@mail.gmail.com>
On Tuesday 30 October 2012 06:42 PM, Anderson Lizardo wrote:
> Hi Ajay,
>
> On Sun, Oct 28, 2012 at 8:30 PM, Ajay <ajay.kv@globaledgesoft.com> wrote:
>> Thanks, but "sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 " , this
>> command only sets the advertising data to zero right . so how do i set the
>> adv flag as 0x06 . Which hci command is used for this purpose .
>
> No, this sets adv. data to have "Flags" AD set to 0x06. But you missed
> the second line of the command:
>
> sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 \
> $(perl -e 'print "00 " x 28')
>
> The second line is important because it fills the other bytes with
> zero (which some controllers require).
>
> Regards,
>
ya , i got your point ,advertiser is informing the remote device ,
that it is not BR/EDR capable .That is done and device is connecting now.
But still i dont know, how to do le specific pairing and
start_encryption enable(part of le pairing) . Is there any tool in bluez
providing LE pairing before connecting the devices (want to try with 2
ubuntu pc's ).
--
Thanks & regards
AJAY KV
GlobalEdge software Ltd
8892753703
^ permalink raw reply
* Re: BLE issue: Start_LE_Encryption fails
From: Ajay @ 2012-10-29 0:30 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_NHaBzobi=k3cMaM-J_3d6R7FCEvfrSJWbkiKxKpjKHWA@mail.gmail.com>
On Tuesday 30 October 2012 05:20 PM, Anderson Lizardo wrote:
> [Forgot to reply to the list]
>
> On Tue, Oct 30, 2012 at 7:49 AM, Anderson Lizardo
> <anderson.lizardo@openbossa.org> wrote:
>> Hi Ajay,
>>
>> On Sun, Oct 28, 2012 at 1:08 PM, Ajay <ajay.kv@globaledgesoft.com> wrote:
>>> Hi,
>>> I am getting le_long_term_key_negative reply from the remote device
>>> , on sending le_start_encryption . I am testing this with 2 ubuntu
>>> machines(3.2.5) with IOGEAR dual mode dongles .
>>
>> To connect to a dual mode dongle, you need to set LE Adv. flags to
>> 0x06 (which means general discoverable + BR/EDR not supported) on the
>> acceptor side. You can use this command (on the acceptor/slave side):
>>
>> sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 \
>> $(perl -e 'print "00 " x 28')
>>
>> Next, enable LE advertising:
>>
>> sudo hciconfig hci0 leadv
>>
>> On the initiator/master side, run "hcitool lescan" and try pairing again.
>
> Regards,
>
Thanks, but "sudo hcitool -i hci0 cmd 0x08 0x0008 03 02 01 06 " , this
command only sets the advertising data to zero right . so how do i set
the adv flag as 0x06 . Which hci command is used for this purpose .
--
Thanks & regards
AJAY KV
GlobalEdge software Ltd
8892753703
^ permalink raw reply
* BLE GATT subcriber example?
From: Couch, Kelly J @ 2012-10-28 21:27 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
Hi,
I'm interested in building a C application that utilizes BLE GATT via DBUS. However, I have been unable to identify a good source of documentation or example that demonstrates how.
How to subscribe to attribute/characteristic change notifications?
So, far I am able to utilize Bluez dbus interface to discover, pair, observe connect/disconnect events. But unable to use DiscoverServices, etc..
Any suggestions are greatly appreciated.
-Kelly
^ permalink raw reply
* Crashing bluetoothd when keyboard enters sleep mode / stand-by
From: Patkos Csaba @ 2012-10-28 18:46 UTC (permalink / raw)
To: linux-bluetooth
Hi,
When my keyboard enters stand-by and disconnects from the computer I see
high cpu usage by bluetoothd. Sometimes, not always, if I don't wake up
the keyboard, bluetoothd will crash leaving this in /var/log/messages:
Oct 28 18:04:49 localhost kernel: [27658.431018] hid-generic
0005:045E:077C.0013: unknown main item tag 0x0
Oct 28 18:04:49 localhost kernel: [27658.431243] input: Microsoft Sculpt
Touch Mouse as
/devices/pci0000:00/0000:00:1d.1/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:45/input32
Oct 28 18:04:49 localhost kernel: [27658.431438] hid-generic
0005:045E:077C.0013: input,hidraw3: BLUETOOTH HID v1.1e Mouse [Microsoft
Sculpt Touch Mouse] on 00:15:83:3D:0A:57
There are no such problems with the mouse, which, as well as the keyboard,
enters stand-by if not used. I have bluez 4.101 provided by Sabayon Linux.
I don't know if it is related, but there is also a problem with the
keyboard state after starting bluetoothd. The initial state of the
keyboard is "disconnected" which is correct. After hitting a key the
keyboard tries to connect, state changes to "connected" but keyboard
doesn't work and nothing is printed in the logs. If I do a disconnect from
the KDE's bluedevil interface, or from the console by running "hcitool dc
7C:1E:52:A8:47:74" and than hit a key again, the keyboard is correctly
detected and working.
I have this bluetooth keyboard:
Oct 28 18:04:49 localhost kernel: [27658.427978] hid-generic
0005:045E:0762.0012: unknown main item tag 0x0
Oct 28 18:04:49 localhost kernel: [27658.428887] input: Microsoft
Bluetooth Mobile Keyboard 6000 as
/devices/pci0000:00/0000:00:1d.1/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:42/input31
Oct 28 18:04:49 localhost kernel: [27658.429030] hid-generic
0005:045E:0762.0012: input,hidraw2: BLUETOOTH HID v0.13 Keyboard
[Microsoft Bluetooth Mobile Keyboard 6000] on 00:15:83:3D:0A:57
With this bluetooth mouse:
Oct 28 18:04:49 localhost kernel: [27658.431018] hid-generic
0005:045E:077C.0013: unknown main item tag 0x0
Oct 28 18:04:49 localhost kernel: [27658.431243] input: Microsoft Sculpt
Touch Mouse as
/devices/pci0000:00/0000:00:1d.1/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:45/input32
Oct 28 18:04:49 localhost kernel: [27658.431438] hid-generic
0005:045E:077C.0013: input,hidraw3: BLUETOOTH HID v1.1e Mouse [Microsoft
Sculpt Touch Mouse] on 00:15:83:3D:0A:57
Running on this usb-bluetooth adapter:
localhost ~ # lsusb -v
Bus 003 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth
Dongle (HCI mode)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 224 Wireless
bDeviceSubClass 1 Radio Frequency
bDeviceProtocol 1 Bluetooth
bMaxPacketSize0 64
idVendor 0x0a12 Cambridge Silicon Radio, Ltd
idProduct 0x0001 Bluetooth Dongle (HCI mode)
bcdDevice 31.64
iManufacturer 0
iProduct 0
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 177
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0000 1x 0 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0000 1x 0 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0009 1x 9 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0009 1x 9 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 2
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0011 1x 17 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0011 1x 17 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 3
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0019 1x 25 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0019 1x 25 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 4
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0021 1x 33 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0021 1x 33 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 5
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0031 1x 49 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0031 1x 49 bytes
bInterval 1
Device Status: 0x0001
Self Powered
--
ing. Patkós Csaba
Software Developer @ Syneto SRL (http://www.syneto.net)
Member of The Romanian Mandriva Users Group (http://www.mandrivausrs.ro)
----
I use Dropbox. Do you? http://db.tt/IqeKInu
^ permalink raw reply
* BLE issue: Start_LE_Encryption fails
From: Ajay @ 2012-10-28 17:08 UTC (permalink / raw)
To: linux-bluetooth
Hi,
I am getting le_long_term_key_negative reply from the remote device ,
on sending le_start_encryption . I am testing this with 2 ubuntu
machines(3.2.5) with IOGEAR dual mode dongles .
I did pairing using blueman and got corresponding link key
from(/var/lib/bluetooth) . But i doubt, this key is specific to BR/EDR
not for LE controller , since hcidump is not showing any packets related
to smp .
so please suggest me a way to do pairing using SMP and LE specific
--
Thanks & regards
AJAY KV
GlobalEdge software Ltd
8892753703
^ permalink raw reply
* [RFC v2 obexd 11/11] fuse: Add rename operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 3 +++
fuse/obexfuse.c | 16 ++++++++++++++++
3 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index d0580c2..2487d09 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -689,3 +689,49 @@ void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
free_location(l);
request_wait_free(session);
}
+
+void gobexhlp_mkdir(struct gobexhlp_session* session, const char *path)
+{
+ struct gobexhlp_location *l;
+ struct stat *stbuf;
+
+ g_print("gobexhlp_mkdir(%s)\n", path);
+
+ l = get_location(path);
+ gobexhlp_setpath(session, l->dir);
+
+ request_new(session, g_strdup_printf("mkdir %s", path));
+ /* g_obex_mkdir also sets path, to new folder */
+ g_obex_mkdir(session->obex, l->file, response_func, session,
+ &session->err);
+ g_free(session->setpath);
+ session->setpath = g_strdup(path);
+
+ stbuf = g_malloc0(sizeof(struct stat));
+ stbuf->st_mode = S_IFDIR;
+ stbuf->st_mtime = time(NULL);
+ g_hash_table_replace(session->file_stat, g_strdup(path), stbuf);
+
+ free_location(l);
+ request_wait_free(session);
+}
+
+void gobexhlp_move(struct gobexhlp_session* session, const char *oldpath,
+ const char* newpath)
+{
+ struct gobexhlp_location *l_from, *l_to;
+
+ l_to = get_location(newpath);
+ l_from = get_location(oldpath);
+ gobexhlp_setpath(session, l_from->dir);
+
+ g_print("gobexhlp_move(%s to %s)\n", l_from->file, l_to->file);
+
+ request_new(session, g_strdup_printf("move %s:%s",
+ oldpath, newpath));
+ g_obex_move(session->obex, l_from->file, l_to->file, response_func,
+ session, &session->err);
+ free_location(l_to);
+ free_location(l_from);
+ request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 803cb59..80e3aa8 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -61,3 +61,6 @@ void gobexhlp_put(struct gobexhlp_session* session,
const char *path);
void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
void gobexhlp_delete(struct gobexhlp_session* session, const char *path);
+void gobexhlp_mkdir(struct gobexhlp_session* session, const char *path);
+void gobexhlp_move(struct gobexhlp_session* session, const char *oldpath,
+ const char* newpath);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 2a6ee11..f9f9d0e 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -237,6 +237,20 @@ static int obexfuse_unlink(const char *path)
return session->status;
}
+static int obexfuse_mkdir(const char *path, mode_t mode)
+{
+ gobexhlp_mkdir(session, path);
+
+ return session->status;
+}
+
+static int obexfuse_rename(const char *from, const char *to)
+{
+ gobexhlp_move(session, from, to);
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
@@ -249,6 +263,8 @@ static struct fuse_operations obexfuse_oper = {
.mknod = obexfuse_mknod,
.unlink = obexfuse_unlink,
.rmdir = obexfuse_unlink,
+ .mkdir = obexfuse_mkdir,
+ .rename = obexfuse_rename,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 28 ++++++++++++++++++++++++++++
fuse/helpers.h | 1 +
fuse/obexfuse.c | 9 +++++++++
3 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index cabf8f7..d0580c2 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -618,6 +618,16 @@ void gobexhlp_put(struct gobexhlp_session* session,
g_print("gobexhlp_put(%s%s)\n", l->dir, l->file);
+ if (g_strcmp0(path, session->vtouch_path) == 0 &&
+ session->vtouch == TRUE) {
+ session->vtouch = FALSE;
+ g_free(session->vtouch_path);
+ } else {
+ /* delete existing file */
+ if (session->rtouch == FALSE)
+ gobexhlp_delete(session, path);
+ }
+
gobexhlp_setpath(session, l->dir);
buffer->tmpsize = 0;
session->buffer = buffer;
@@ -661,3 +671,21 @@ void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path)
session->buffer = tmpbuf;
}
+
+void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
+{
+ struct gobexhlp_location *l;
+ l = get_location(path);
+
+ g_print("gobexhlp_delete(%s)\n", l->file);
+
+ gobexhlp_setpath(session, l->dir);
+ request_new(session, g_strdup_printf("delete %s", path));
+ g_obex_delete(session->obex, l->file, response_func, session,
+ &session->err);
+
+ g_hash_table_remove(session->file_stat, path);
+
+ free_location(l);
+ request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index c2b28ca..803cb59 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -60,3 +60,4 @@ void gobexhlp_put(struct gobexhlp_session* session,
struct gobexhlp_buffer *buffer,
const char *path);
void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
+void gobexhlp_delete(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index b4599d8..2a6ee11 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -230,6 +230,13 @@ static int obexfuse_mknod(const char *path, mode_t mode, dev_t dev)
return 0;
}
+static int obexfuse_unlink(const char *path)
+{
+ gobexhlp_delete(session, path);
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
@@ -240,6 +247,8 @@ static struct fuse_operations obexfuse_oper = {
.release = obexfuse_release,
.utimens = obexfuse_utimens,
.mknod = obexfuse_mknod,
+ .unlink = obexfuse_unlink,
+ .rmdir = obexfuse_unlink,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 09/11] fuse: Add touch operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 40 ++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 1 +
fuse/obexfuse.c | 17 +++++++++++++++++
3 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 796c4a3..cabf8f7 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -56,6 +56,8 @@ struct gobexhlp_location {
gchar *file;
};
+void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path);
+
static uint16_t find_rfcomm_uuid(void *user_data)
{
sdp_list_t *pds = (sdp_list_t*) user_data;
@@ -279,6 +281,12 @@ void request_new(struct gobexhlp_session *session,
{
g_print("REQUEST %s\n", name);
+ if (session->vtouch == TRUE) {
+ session->vtouch = FALSE;
+ gobexhlp_touch_real(session, session->vtouch_path);
+ g_free(session->vtouch_path);
+ }
+
if (session->request != NULL)
g_error("Another request (%s) active!\n",
session->request->name);
@@ -621,3 +629,35 @@ void gobexhlp_put(struct gobexhlp_session* session,
free_location(l);
request_wait_free(session);
}
+
+/* virtual file creation */
+void gobexhlp_touch(struct gobexhlp_session* session, const char *path)
+{
+ struct stat *stbuf;
+
+ g_print("gobexhlp_touch(%s)\n", path);
+
+ stbuf = g_malloc0(sizeof(struct stat));
+ stbuf->st_mode = S_IFREG;
+ g_hash_table_replace(session->file_stat, g_strdup(path), stbuf);
+
+ session->vtouch = TRUE;
+ session->vtouch_path = g_strdup(path);
+}
+
+void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path)
+{
+ struct gobexhlp_buffer *buffer, *tmpbuf;
+
+ g_print("gobexhlp_touch_real(%s)\n", path);
+
+ tmpbuf = session->buffer; /* save buffer state */
+
+ buffer = g_malloc0(sizeof(struct gobexhlp_buffer));
+ session->rtouch = TRUE;
+ gobexhlp_put(session, buffer, path);
+ session->rtouch = FALSE;
+ g_free(buffer);
+
+ session->buffer = tmpbuf;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 1eca29d..c2b28ca 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -59,3 +59,4 @@ struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
void gobexhlp_put(struct gobexhlp_session* session,
struct gobexhlp_buffer *buffer,
const char *path);
+void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 900e6d7..b4599d8 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -215,6 +215,21 @@ static int obexfuse_release(const char *path, struct fuse_file_info *fi)
return session->status;
}
+static int obexfuse_utimens(const char *path, const struct timespec tv[2])
+{
+ /*
+ * Important for mknod (touch) operation
+ */
+ return 0;
+}
+
+static int obexfuse_mknod(const char *path, mode_t mode, dev_t dev)
+{
+ gobexhlp_touch(session, path);
+
+ return 0;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
@@ -223,6 +238,8 @@ static struct fuse_operations obexfuse_oper = {
.write = obexfuse_write,
.truncate = obexfuse_truncate,
.release = obexfuse_release,
+ .utimens = obexfuse_utimens,
+ .mknod = obexfuse_mknod,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 08/11] fuse: Add write operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 3 +++
fuse/obexfuse.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 9b453e0..796c4a3 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -577,3 +577,47 @@ struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
return buffer;
}
+
+static gssize async_put_producer(void *buf, gsize len, gpointer user_data)
+{
+ gssize size;
+ struct gobexhlp_session *session = user_data;
+ struct gobexhlp_buffer *buffer = session->buffer;
+
+ size = buffer->size - buffer->tmpsize;
+
+ if (size > len)
+ size = len;
+
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+
+ if (size == 0)
+ return 0;
+
+ memcpy(buf, buffer->data + buffer->tmpsize, size);
+ buffer->tmpsize += size;
+
+ return size;
+}
+
+void gobexhlp_put(struct gobexhlp_session* session,
+ struct gobexhlp_buffer *buffer,
+ const char *path)
+{
+ struct gobexhlp_location *l;
+ l = get_location(path);
+
+ g_print("gobexhlp_put(%s%s)\n", l->dir, l->file);
+
+ gobexhlp_setpath(session, l->dir);
+ buffer->tmpsize = 0;
+ session->buffer = buffer;
+ request_new(session, g_strdup_printf("put %s", path));
+ g_obex_put_req(session->obex, async_put_producer,
+ complete_func, session, &session->err,
+ G_OBEX_HDR_NAME, l->file,
+ G_OBEX_HDR_INVALID);
+ free_location(l);
+ request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index aa2a194..1eca29d 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -56,3 +56,6 @@ struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
const char *path);
struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
const char *path);
+void gobexhlp_put(struct gobexhlp_session* session,
+ struct gobexhlp_buffer *buffer,
+ const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 9fe2dea..900e6d7 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -174,11 +174,55 @@ static int obexfuse_read(const char *path, char *buf, size_t size,
return asize;
}
+static int obexfuse_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ gsize nsize;
+ struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+ if (file_buffer->size < offset + size) {
+ nsize = offset + size;
+ file_buffer->data = g_realloc(file_buffer->data, nsize);
+ file_buffer->size = nsize;
+ } else {
+ nsize = file_buffer->size;
+ }
+
+ file_buffer->edited = TRUE;
+ memcpy(file_buffer->data + offset, buf, size);
+
+ return size;
+}
+
+static int obexfuse_truncate(const char *path, off_t offset)
+{
+ /*
+ * Allow to change the size of a file.
+ */
+ return 0;
+}
+
+static int obexfuse_release(const char *path, struct fuse_file_info *fi)
+{
+ struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+ if (file_buffer->edited == TRUE)
+ gobexhlp_put(session, file_buffer, path); /* send to device */
+
+ g_free(file_buffer->data);
+ g_free(file_buffer);
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
.open = obexfuse_open,
.read = obexfuse_read,
+ .write = obexfuse_write,
+ .truncate = obexfuse_truncate,
+ .release = obexfuse_release,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 2 +
fuse/obexfuse.c | 32 ++++++++++++++++++++++++++++
3 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index a10b706..9b453e0 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -515,3 +515,65 @@ struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
{
return g_hash_table_lookup(session->file_stat, path);
}
+
+static struct gobexhlp_location *get_location(const char *path)
+{
+ struct gobexhlp_location *location;
+ gchar **directories;
+ guint i, len, fid = 0;
+
+ location = g_malloc0(sizeof(*location));
+ directories = g_strsplit(path, "/", -1);
+ len = g_strv_length(directories);
+
+ for (i = 0; i < len; i++)
+ if (directories[i][0] != '\0') /* protect multi slashes */
+ fid = i; /* last nonempty is a file */
+
+ location->file = g_strdup(directories[fid]);
+ directories[fid][0] = '\0'; /* remove file */
+ location->dir = g_strjoinv("/", directories);
+
+ g_strfreev(directories);
+
+ return location;
+}
+
+void free_location(struct gobexhlp_location *location)
+{
+ g_free(location->file);
+ g_free(location->dir);
+ g_free(location);
+}
+
+struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
+ const char *path)
+{
+ struct gobexhlp_location *l;
+ struct gobexhlp_buffer *buffer;
+ struct stat *stfile;
+ l = get_location(path);
+
+ g_print("gobexhlp_get(%s%s)\n", l->dir, l->file);
+
+ stfile = gobexhlp_getattr(session, path);
+ if (stfile == NULL)
+ return NULL;
+
+ buffer = g_malloc0(sizeof(*buffer));
+
+ if (stfile->st_size == 0)
+ return buffer;
+
+ gobexhlp_setpath(session, l->dir);
+ request_new(session, g_strdup_printf("get %s", path));
+ session->buffer = buffer;
+ g_obex_get_req(session->obex, async_get_consumer,
+ complete_func, session, &session->err,
+ G_OBEX_HDR_NAME, l->file,
+ G_OBEX_HDR_INVALID);
+ free_location(l);
+ request_wait_free(session);
+
+ return buffer;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 047abae..aa2a194 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -54,3 +54,5 @@ void gobexhlp_disconnect(struct gobexhlp_session* session);
GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
const char *path);
+struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
+ const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index f4e85fa..9fe2dea 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -144,9 +144,41 @@ static int obexfuse_getattr(const char *path, struct stat *stbuf)
return res;
}
+static int obexfuse_open(const char *path, struct fuse_file_info *fi)
+{
+ struct gobexhlp_buffer *file_buffer;
+
+ file_buffer = gobexhlp_get(session, path);
+
+ if (file_buffer == NULL)
+ return -ENOENT;
+
+ fi->fh = (uint64_t)file_buffer;
+
+ return session->status;
+}
+
+static int obexfuse_read(const char *path, char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ gsize asize;
+ struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+ asize = file_buffer->size - offset;
+
+ if (asize > size)
+ asize = size;
+
+ memcpy(buf, file_buffer->data + offset, asize);
+
+ return asize;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
+ .open = obexfuse_open,
+ .read = obexfuse_read,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 06/11] fuse: Add getattr operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 6 ++++++
fuse/helpers.h | 2 ++
fuse/obexfuse.c | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index cb0b51d..a10b706 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -509,3 +509,9 @@ GList *gobexhlp_listfolder(struct gobexhlp_session* session,
return session->lsfiles;
}
+
+struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
+ const char *path)
+{
+ return g_hash_table_lookup(session->file_stat, path);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 546d79c..047abae 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -52,3 +52,5 @@ struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
void gobexhlp_disconnect(struct gobexhlp_session* session);
GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
+struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
+ const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 5de82ec..f4e85fa 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -111,8 +111,42 @@ static int obexfuse_readdir(const char *path, void *buf,
return session->status;
}
+static int obexfuse_getattr(const char *path, struct stat *stbuf)
+{
+ int res = 0;
+ struct stat *stfile;
+
+ memset(stbuf, 0, sizeof(struct stat));
+
+ if (strcmp(path, "/") == 0) {
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ } else {
+ stfile = gobexhlp_getattr(session, path);
+
+ if (stfile == NULL)
+ return -ENOENT;
+
+ if (stfile->st_mode == S_IFREG)
+ stbuf->st_mode = stfile->st_mode | 0666;
+ else /* S_IFDIR */
+ stbuf->st_mode = stfile->st_mode | 0755;
+
+ stbuf->st_nlink = 1;
+ stbuf->st_size = stfile->st_size;
+ stbuf->st_mtime = stbuf->st_atime = stbuf->st_ctime =
+ stfile->st_mtime;
+ stbuf->st_blksize = 512;
+ stbuf->st_blocks = (stbuf->st_size + stbuf->st_blksize)
+ / stbuf->st_blksize;
+ }
+
+ return res;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
+ .getattr = obexfuse_getattr,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 05/11] fuse: Add readdir operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 2 +
fuse/obexfuse.c | 23 ++++++++++
3 files changed, 153 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 1b8082f..cb0b51d 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -381,3 +381,131 @@ void gobexhlp_setpath(struct gobexhlp_session *session, const char *path)
g_strfreev(path_v);
}
+
+static void listfolder_xml_element(GMarkupParseContext *ctxt,
+ const gchar *element, const gchar **names,
+ const gchar **values, gpointer user_data,
+ GError **gerr)
+{
+ gchar *key, *pathname, *name = NULL;
+ struct gobexhlp_session *session = user_data;
+ struct stat *stbuf;
+ gint i = 0;
+
+ stbuf = g_malloc0(sizeof(struct stat));
+
+ if ((strcasecmp("file", element) == 0)) {
+ stbuf->st_mode = S_IFREG;
+ } else if ((strcasecmp("folder", element)) == 0) {
+ stbuf->st_mode = S_IFDIR;
+ stbuf->st_mtime = time(NULL);
+ } else {
+ g_free(stbuf);
+ return;
+ }
+
+ for (key = (gchar *) names[i]; key; key = (gchar *) names[++i]) {
+ if (g_str_equal("name", key) == TRUE) {
+ session->lsfiles = g_list_append(session->lsfiles,
+ g_strdup(values[i]));
+ name = g_strdup(values[i]);
+
+ } else if (g_str_equal("size", key) == TRUE) {
+ guint64 size;
+ size = g_ascii_strtoll(values[i], NULL, 10);
+ stbuf->st_size = size;
+
+ } else if (g_str_equal("created", key) == TRUE) {
+ GTimeVal time;
+ GDateTime *datetime;
+ g_time_val_from_iso8601(values[i], &time);
+ datetime = g_date_time_new_from_timeval_utc(&time);
+ stbuf->st_mtime = g_date_time_to_unix(datetime);
+ }
+ }
+
+ if (g_str_equal("/", session->setpath) == TRUE)
+ pathname = g_strdup_printf("/%s", name);
+ else
+ pathname = g_strdup_printf("%s/%s", session->setpath, name);
+
+ g_hash_table_replace(session->file_stat, pathname, stbuf);
+ g_free(name);
+}
+
+static const GMarkupParser parser = {
+ listfolder_xml_element,
+ NULL, NULL, NULL, NULL
+};
+
+static void complete_listfolder_func(GObex *obex, GError *err,
+ gpointer user_data)
+{
+ GMarkupParseContext *ctxt;
+ struct gobexhlp_session *session = user_data;
+ struct gobexhlp_buffer *buffer = session->buffer;
+
+ if (err == NULL) {
+ ctxt = g_markup_parse_context_new(&parser, 0, session, NULL);
+ g_markup_parse_context_parse(ctxt, buffer->data, buffer->size,
+ NULL);
+ g_markup_parse_context_free(ctxt);
+ }
+
+ complete_func(obex, err, user_data);
+}
+
+static gboolean async_get_consumer(const void *buf, gsize len,
+ gpointer user_data)
+{
+ struct gobexhlp_session *session = user_data;
+ struct gobexhlp_buffer *buffer = session->buffer;
+
+ if (buffer->size == 0)
+ buffer->data = g_malloc0(sizeof(char) * len);
+ else
+ buffer->data = g_realloc(buffer->data, buffer->size + len);
+
+ memcpy(buffer->data + buffer->size, buf, len);
+ buffer->size += len;
+
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+
+ return TRUE;
+}
+
+GList *gobexhlp_listfolder(struct gobexhlp_session* session,
+ const char *path)
+{
+ struct gobexhlp_buffer *buffer;
+ GObexPacket *req;
+ guint reqpkt;
+
+ gobexhlp_setpath(session, path);
+
+ g_print("gobexhlp_listfolder(%s)\n", path);
+
+ if (session->lsfiles != NULL) {
+ g_list_free_full(session->lsfiles, g_free);
+ session->lsfiles = NULL;
+ }
+
+ session->lsfiles = g_list_alloc();
+ buffer = g_malloc0(sizeof(struct gobexhlp_buffer));
+ session->buffer = buffer;
+
+ request_new(session, g_strdup_printf("listfolder %s", path));
+ req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID);
+ g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, OBEX_FTP_LS,
+ strlen(OBEX_FTP_LS) + 1);
+ reqpkt = g_obex_get_req_pkt(session->obex, req,
+ async_get_consumer,
+ complete_listfolder_func,
+ session, &session->err);
+ request_wait_free(session);
+ g_free(buffer->data);
+ g_free(buffer);
+
+ return session->lsfiles;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 29dc6cf..546d79c 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -50,3 +50,5 @@ struct gobexhlp_session {
struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
const char *dstsrc);
void gobexhlp_disconnect(struct gobexhlp_session* session);
+
+GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 79eb990..5de82ec 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -89,7 +89,30 @@ void obexfuse_destroy()
g_thread_join(main_gthread);
}
+static int obexfuse_readdir(const char *path, void *buf,
+ fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int len, i;
+ gchar *string;
+ GList *files;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+
+ files = gobexhlp_listfolder(session, path);
+ len = g_list_length(files);
+
+ for (i = 1; i < len; i++) { /* element for i==0 is NULL */
+ string = g_list_nth_data(files, i);
+ filler(buf, string, NULL, 0);
+ }
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
+ .readdir = obexfuse_readdir,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 856e1d5..1b8082f 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
g_free(session);
}
+
+void request_new(struct gobexhlp_session *session,
+ gchar *name)
+{
+ g_print("REQUEST %s\n", name);
+
+ if (session->request != NULL)
+ g_error("Another request (%s) active!\n",
+ session->request->name);
+
+ session->status = 0;
+ session->request = g_malloc0(sizeof(struct gobexhlp_request));
+ session->request->name = name;
+
+ /*
+ * suspend/resume operations recreates g_io_add_watch(),
+ * it fixes obex->io freeze during transfer
+ */
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+}
+
+void request_wait_free(struct gobexhlp_session *session)
+{
+ g_print("WAIT for %s\n", session->request->name);
+
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+
+ if (session->err != NULL) {
+ g_print("ERROR: %s (%d)\n", session->err->message,
+ session->err->code);
+ g_error_free(session->err);
+ raise(SIGTERM);
+ return;
+ }
+
+ g_mutex_lock(gobexhlp_mutex);
+
+ while (session->request->complete != TRUE)
+ g_cond_wait(gobexhlp_cond, gobexhlp_mutex);
+
+ g_mutex_unlock(gobexhlp_mutex);
+
+ g_free(session->request->name);
+ g_free(session->request);
+ session->request = NULL;
+}
+
+static void complete_func(GObex *obex, GError *err,
+ gpointer user_data)
+{
+ struct gobexhlp_session *session = user_data;
+
+ if (err != NULL) {
+ g_print("ERROR: %s\n", err->message);
+ session->status = -ECANCELED;
+ g_error_free(err);
+ } else {
+ g_print("COMPLETE %s\n", session->request->name);
+ }
+
+ g_mutex_lock(gobexhlp_mutex);
+ session->request->complete = TRUE;
+ g_cond_signal(gobexhlp_cond);
+ g_mutex_unlock(gobexhlp_mutex);
+}
+
+static void response_func(GObex *obex, GError *err, GObexPacket *rsp,
+ gpointer user_data)
+{
+ complete_func(obex, err, user_data);
+}
+
+void gobexhlp_setpath(struct gobexhlp_session *session, const char *path)
+{
+ guint i = 0, split = 0;
+ gchar **path_v;
+ gsize len;
+
+ g_print("gobexhlp_setpath(%s)\n", path);
+
+ if (g_str_has_prefix(path, session->setpath)) {
+ split = strlen(session->setpath);
+ } else {
+ request_new(session, g_strdup_printf("setpath root"));
+ g_obex_setpath(session->obex, "", response_func,
+ session, &session->err);
+ request_wait_free(session);
+ }
+
+ path_v = g_strsplit(path+split, "/", -1);
+ len = g_strv_length(path_v);
+
+ for (i = 0; i < len; i++)
+ if (path_v[i][0] != '\0') {
+ request_new(session,
+ g_strdup_printf("setpath %s", path_v[i]));
+ g_obex_setpath(session->obex, path_v[i],
+ response_func, session, &session->err);
+ request_wait_free(session);
+ }
+
+ g_free(session->setpath);
+ session->setpath = g_strdup(path);
+
+ g_strfreev(path_v);
+}
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
fuse/helpers.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 4 +
fuse/obexfuse.c | 40 ++++++++++
3 files changed, 265 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index c36072d..856e1d5 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -43,6 +43,9 @@
#define OBEX_FTP_LS "x-obex/folder-listing"
+static GCond *gobexhlp_cond;
+static GMutex *gobexhlp_mutex;
+
struct gobexhlp_request {
gchar *name;
gboolean complete;
@@ -52,3 +55,221 @@ struct gobexhlp_location {
gchar *dir;
gchar *file;
};
+
+static uint16_t find_rfcomm_uuid(void *user_data)
+{
+ sdp_list_t *pds = (sdp_list_t*) user_data;
+ uint16_t channel = 0;
+
+ for (;pds;pds = pds->next) {
+ sdp_data_t *d = (sdp_data_t*)pds->data;
+ int proto = 0;
+ for (; d; d = d->next) {
+ switch(d->dtd) {
+ case SDP_UUID16:
+ case SDP_UUID32:
+ case SDP_UUID128:
+ proto = sdp_uuid_to_proto(&d->val.uuid);
+ break;
+ case SDP_UINT8:
+ if (proto == RFCOMM_UUID)
+ channel = d->val.int8;
+ break;
+ }
+ }
+ }
+ return channel;
+}
+
+static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
+{
+ sdp_session_t *sdp;
+ sdp_list_t *r, *search_list, *attrid_list;
+ sdp_list_t *response_list = NULL;
+ uuid_t uuid;
+
+ /* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
+ uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
+ 0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ uint32_t range = 0x0000ffff;
+ uint16_t channel = 0;
+
+ sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
+ if (sdp == NULL)
+ return channel;
+
+ sdp_uuid128_create(&uuid, uuid_int);
+ search_list = sdp_list_append(NULL, &uuid);
+ attrid_list = sdp_list_append(NULL, &range);
+ sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
+ attrid_list, &response_list);
+ r = response_list;
+
+ for (; r;r = r->next) {
+ sdp_record_t *rec = (sdp_record_t*) r->data;
+ sdp_list_t *proto_list;
+
+ if (sdp_get_access_protos(rec, &proto_list ) == 0) {
+ sdp_list_t *p = proto_list;
+ for (; p; p = p->next) {
+ sdp_list_t *pds = (sdp_list_t*) p->data;
+ channel = find_rfcomm_uuid(pds);
+ sdp_list_free((sdp_list_t*) p->data, 0);
+ }
+ sdp_list_free(proto_list, 0);
+ }
+ sdp_record_free(rec);
+ }
+ sdp_close(sdp);
+
+ g_free(search_list);
+ g_free(attrid_list);
+ g_free(response_list);
+
+ return channel;
+}
+
+/* taken from client/bluetooth.c - bluetooth_getpacketopt */
+static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
+{
+ int sk = g_io_channel_unix_get_fd(io);
+ int type;
+ int omtu = -1;
+ int imtu = -1;
+ socklen_t len = sizeof(int);
+
+ if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
+ return -errno;
+
+ if (type != SOCK_SEQPACKET)
+ return -EINVAL;
+
+ if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
+ BT_IO_OPT_IMTU, &imtu,
+ BT_IO_OPT_INVALID))
+ return -EINVAL;
+
+ if (tx_mtu)
+ *tx_mtu = omtu;
+
+ if (rx_mtu)
+ *rx_mtu = imtu;
+
+ return 0;
+}
+
+static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
+ gpointer user_data)
+{
+ if (err != NULL) {
+ g_debug("Connect failed: %s\n", err->message);
+ g_error_free(err);
+ } else {
+ g_debug("Connect succeeded\n");
+ }
+}
+
+static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
+{
+ struct gobexhlp_session *session = user_data;
+ GObexTransportType type;
+ int tx_mtu = -1;
+ int rx_mtu = -1;
+
+ if (err != NULL) {
+ g_printerr("%s\n", err->message);
+ g_error_free(err);
+ return;
+ }
+
+ g_debug("Bluetooth socket connected\n");
+
+ g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref(session->io, TRUE);
+
+ if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
+ type = G_OBEX_TRANSPORT_PACKET;
+ g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
+ } else {
+ type = G_OBEX_TRANSPORT_STREAM;
+ g_debug("STREAM transport\n");
+ }
+
+ session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
+ g_obex_connect(session->obex, obex_callback, session, NULL,
+ G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
+ OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
+}
+
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+ const char *dststr)
+{
+ struct gobexhlp_session *session;
+ uint16_t channel;
+ bdaddr_t src, dst;
+
+ session = g_try_malloc0(sizeof(struct gobexhlp_session));
+ if (session == NULL)
+ return NULL;
+
+ if (srcstr == NULL)
+ bacpy(&src, BDADDR_ANY);
+ else
+ str2ba(srcstr, &src);
+
+ str2ba(dststr, &dst);
+ channel = get_ftp_channel(&src, &dst);
+
+ if (channel == 0)
+ return NULL;
+
+ if (channel > 31)
+ session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
+ session, NULL, &session->err,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_PSM, channel,
+ BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
+ BT_IO_OPT_OMTU, BT_TX_MTU,
+ BT_IO_OPT_IMTU, BT_RX_MTU,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_INVALID);
+ else
+ session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
+ session, NULL, &session->err,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_CHANNEL, channel,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_INVALID);
+
+ if (session->err != NULL)
+ return NULL;
+
+ session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
+ g_free, g_free);
+ session->setpath = g_strdup("/");
+
+ gobexhlp_mutex = g_mutex_new();
+ gobexhlp_cond = g_cond_new();
+
+ return session;
+}
+
+void gobexhlp_disconnect(struct gobexhlp_session* session)
+{
+ if (session == NULL)
+ return;
+
+ g_obex_unref(session->obex);
+ g_free(session->io);
+
+ g_hash_table_remove_all(session->file_stat);
+ g_list_free_full(session->lsfiles, g_free);
+ g_free(session->setpath);
+
+ g_mutex_free(gobexhlp_mutex);
+ g_cond_free(gobexhlp_cond);
+
+ g_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 142403f..29dc6cf 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -46,3 +46,7 @@ struct gobexhlp_session {
int status;
GError *err;
};
+
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+ const char *dstsrc);
+void gobexhlp_disconnect(struct gobexhlp_session* session);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index fe4f4da..79eb990 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -33,6 +33,10 @@
#include "helpers.h"
+struct gobexhlp_session* session = NULL;
+static GMainLoop *main_loop;
+static GThread *main_gthread;
+
struct options {
char* dststr;
char* srcstr;
@@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
FUSE_OPT_END
};
+gpointer main_loop_func(gpointer user_data)
+{
+ main_loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(main_loop);
+
+ return 0;
+}
+
+void* obexfuse_init(struct fuse_conn_info *conn)
+{
+ main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
+
+ conn->async_read = 0;
+ conn->want &= ~FUSE_CAP_ASYNC_READ;
+
+ return 0;
+}
+
+void obexfuse_destroy()
+{
+ gobexhlp_disconnect(session);
+ g_main_loop_quit(main_loop);
+ g_thread_join(main_gthread);
+}
+
static struct fuse_operations obexfuse_oper = {
+ .init = obexfuse_init,
+ .destroy = obexfuse_destroy,
};
static int obexfuse_opt_proc(void *data, const char *arg, int key,
@@ -111,6 +142,15 @@ int main(int argc, char *argv[])
g_thread_init(NULL);
+ session = gobexhlp_connect(options.srcstr, options.dststr);
+ if (session == NULL || session->io == NULL) {
+ g_printerr("Connection to %s failed\n", options.dststr);
+ gobexhlp_disconnect(session);
+ return -EHOSTUNREACH;
+ } else {
+ g_print("Connected\nMounting %s\n", options.dststr);
+ }
+
fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
In-Reply-To: <1351384166-15586-1-git-send-email-dmp0x7c5@gmail.com>
---
Makefile.am | 9 +++++++++
configure.ac | 15 +++++++++++++++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 724dd5d..01441dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,6 +132,15 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
endif
+if FUSE
+bin_PROGRAMS = fuse/obexfuse
+
+fuse_obexfuse_SOURCES = $(gobex_sources) $(btio_sources) \
+ fuse/helpers.c fuse/obexfuse.c
+
+fuse_obexfuse_LDADD = @GLIB_LIBS@ @GTHREAD_LIBS@ @BLUEZ_LIBS@ @FUSE_LIBS@
+endif
+
service_DATA = $(service_in_files:.service.in=.service)
AM_CFLAGS = @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ @GTHREAD_CFLAGS@ @GLIB_CFLAGS@ \
diff --git a/configure.ac b/configure.ac
index c8e61ac..f380481 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,4 +180,19 @@ AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no")
AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
+AC_ARG_ENABLE(fuse, AC_HELP_STRING([--enable-fuse],
+ [Build obexfuse]), [
+ PKG_CHECK_MODULES(FUSE, fuse, dummy=yes,
+ AC_MSG_ERROR(FUSE is required))
+ AC_SUBST(FUSE_CFLAGS)
+ AC_SUBST(FUSE_LIBS)
+ enable_fuse=${enableval}
+
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0, dummy=yes,
+ AC_MSG_ERROR(libgthread is required))
+ AC_SUBST(GTHREAD_CFLAGS)
+ AC_SUBST(GTHREAD_LIBS)
+])
+AM_CONDITIONAL(FUSE, test "${enable_fuse}" != "no")
+
AC_OUTPUT(Makefile)
--
1.7.8.6
^ permalink raw reply related
* [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 54 +++++++++++++++++++++++++
fuse/helpers.h | 48 ++++++++++++++++++++++
fuse/obexfuse.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 221 insertions(+), 0 deletions(-)
create mode 100644 fuse/helpers.c
create mode 100644 fuse/helpers.h
create mode 100644 fuse/obexfuse.c
diff --git a/fuse/helpers.c b/fuse/helpers.c
new file mode 100644
index 0000000..c36072d
--- /dev/null
+++ b/fuse/helpers.c
@@ -0,0 +1,54 @@
+/*
+ * OBEX Filesystem in Userspace
+ *
+ * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <gobex/gobex.h>
+#include <btio/btio.h>
+
+#include <glib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#define BT_RX_MTU 32767
+#define BT_TX_MTU 32767
+
+#include "helpers.h"
+
+#define OBEX_FTP_UUID \
+ "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
+#define OBEX_FTP_UUID_LEN 16
+
+#define OBEX_FTP_LS "x-obex/folder-listing"
+
+struct gobexhlp_request {
+ gchar *name;
+ gboolean complete;
+};
+
+struct gobexhlp_location {
+ gchar *dir;
+ gchar *file;
+};
diff --git a/fuse/helpers.h b/fuse/helpers.h
new file mode 100644
index 0000000..142403f
--- /dev/null
+++ b/fuse/helpers.h
@@ -0,0 +1,48 @@
+/*
+ * OBEX Filesystem in Userspace
+ *
+ * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <gobex/gobex.h>
+#include <glib.h>
+
+struct gobexhlp_request;
+
+struct gobexhlp_buffer {
+ void *data;
+ gsize tmpsize;
+ gsize size;
+ gboolean edited;
+};
+
+struct gobexhlp_session {
+ GObex *obex;
+ GList *lsfiles;
+ GIOChannel *io;
+ GHashTable *file_stat;
+ gchar *setpath;
+ struct gobexhlp_request *request;
+ struct gobexhlp_buffer *buffer;
+ gboolean vtouch;
+ gchar *vtouch_path;
+ gboolean rtouch;
+ int status;
+ GError *err;
+};
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
new file mode 100644
index 0000000..fe4f4da
--- /dev/null
+++ b/fuse/obexfuse.c
@@ -0,0 +1,119 @@
+/*
+ * OBEX Filesystem in Userspace
+ *
+ * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define FUSE_USE_VERSION 26
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fuse.h>
+#include <fuse/fuse_opt.h>
+
+#include "helpers.h"
+
+struct options {
+ char* dststr;
+ char* srcstr;
+} options;
+
+#define GOBEXFUSE_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v }
+
+enum
+{
+ KEY_VERSION,
+ KEY_HELP,
+};
+
+static struct fuse_opt obexfuse_opts[] =
+{
+ GOBEXFUSE_OPT_KEY("--target=%s",dststr, 0),
+ GOBEXFUSE_OPT_KEY("-t %s", dststr, 0),
+ GOBEXFUSE_OPT_KEY("--source=%s",srcstr, 0),
+ GOBEXFUSE_OPT_KEY("-s %s", srcstr, 0),
+
+ FUSE_OPT_KEY("-V", KEY_VERSION),
+ FUSE_OPT_KEY("--version", KEY_VERSION),
+ FUSE_OPT_KEY("-h", KEY_HELP),
+ FUSE_OPT_KEY("--help", KEY_HELP),
+ FUSE_OPT_END
+};
+
+static struct fuse_operations obexfuse_oper = {
+};
+
+static int obexfuse_opt_proc(void *data, const char *arg, int key,
+ struct fuse_args *outargs)
+{
+ switch (key) {
+ case KEY_HELP:
+ g_printerr("Usage: %s mountpoint [options]\n"
+ "\n"
+ "general options:\n"
+ " -o opt,[opt...] mount options\n"
+ " -h --help print help\n"
+ " -V --version print version\n"
+ "\n"
+ "obexfuse options:\n"
+ " -t --target target btaddr "
+ "(mandatory)\n"
+ " -s --source source btaddr\n"
+ "\n"
+ , outargs->argv[0]);
+ fuse_opt_add_arg(outargs, "-ho");
+ fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
+ exit(1);
+ case KEY_VERSION:
+ g_print("obexfuse upon:\n");
+ fuse_opt_add_arg(outargs, "--version");
+ fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
+ exit(0);
+ }
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ int retfuse;
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+
+ memset(&options, 0, sizeof(struct options));
+
+ if (fuse_opt_parse(&args, &options, obexfuse_opts,
+ obexfuse_opt_proc) == -1)
+ return -EINVAL;
+
+ if (options.dststr == NULL) {
+ g_printerr("Target not specified\n");
+ return -EINVAL;
+ }
+
+ g_thread_init(NULL);
+
+ fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
+ retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
+
+ fuse_opt_free_args(&args);
+ return retfuse;
+}
--
1.7.8.6
^ permalink raw reply related
* Re: [RFC v2 1/2] Bluetooth: Add driver extension for vendor device setup
From: Marcel Holtmann @ 2012-10-27 23:34 UTC (permalink / raw)
To: Tedd Ho-Jeong An; +Cc: linux-bluetooth, albert.o.ho, johan.hedberg, tedd.hj.an
In-Reply-To: <2721081.2F6GJ3v4qE@tedd-ubuntu>
Hi Tedd,
> This patch provides an extension of btusb to support device vendor
> can implement their own module like mini driver to execute device
> specific setup before the BT stack sends generic BT device
> initialization.
>
> Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
> ---
> drivers/bluetooth/btusb.c | 194 +++++++++++++++++++++++++-------------
> drivers/bluetooth/btusb.h | 53 +++++++++++
> include/net/bluetooth/hci.h | 2 +
> include/net/bluetooth/hci_core.h | 8 ++
> net/bluetooth/hci_core.c | 28 +++++-
> 5 files changed, 220 insertions(+), 65 deletions(-)
> create mode 100644 drivers/bluetooth/btusb.h
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index f637c25..d3f8e7d 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -26,6 +26,7 @@
>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> +#include "btusb.h"
>
> #define VERSION "0.6"
>
> @@ -39,14 +40,52 @@ static bool reset = 1;
>
> static struct usb_driver btusb_driver;
>
> -#define BTUSB_IGNORE 0x01
> -#define BTUSB_DIGIANSWER 0x02
> -#define BTUSB_CSR 0x04
> -#define BTUSB_SNIFFER 0x08
> -#define BTUSB_BCM92035 0x10
> -#define BTUSB_BROKEN_ISOC 0x20
> -#define BTUSB_WRONG_SCO_MTU 0x40
> -#define BTUSB_ATH3012 0x80
> +/* CHECKME: supporting mini-driver requires changing usage of driver_info from
> + * flags to static const struct. */
> +static const struct btusb_driver_info generic = {
> + .description = "BTUSB Generic",
> + .flags = BTUSB_GENERIC,
> +};
> +
> +static const struct btusb_driver_info ignore = {
> + .description = "BTUSB Ignore",
> + .flags = BTUSB_IGNORE,
> +};
> +
> +static const struct btusb_driver_info digianswer = {
> + .description = "BTUSB DIGIANSWER",
> + .flags = BTUSB_DIGIANSWER,
> +};
> +
> +static const struct btusb_driver_info csr = {
> + .description = "BTUSB CSR",
> + .flags = BTUSB_CSR,
> +};
> +
> +static const struct btusb_driver_info sniffer = {
> + .description = "BTUSB Sniffer",
> + .flags = BTUSB_SNIFFER,
> +};
> +
> +static const struct btusb_driver_info bcm92035 = {
> + .description = "BTUSB BCM92035",
> + .flags = BTUSB_BCM92035,
> +};
> +
> +static const struct btusb_driver_info broken_isoc = {
> + .description = "BTUSB Broken ISOC",
> + .flags = BTUSB_BROKEN_ISOC,
> +};
> +
> +static const struct btusb_driver_info wrong_sco_mtu = {
> + .description = "BTUSB Wrong SCO MTU",
> + .flags = BTUSB_WRONG_SCO_MTU,
> +};
> +
> +static const struct btusb_driver_info ath3012 = {
> + .description = "BTUSB Ath3012",
> + .flags = BTUSB_ATH3012,
> +};
I do not get why are you doing this. Didn't I mention last time to not
touch the blacklist handling?
You do realize that the exported btusb_probe() does not have to be the
same one as what btusb.ko itself provides as probe callback. Trying to
squeeze the usb_device_id from btusb.ko and eventual external drivers
into the same structure is just bloating the code.
Keep in mind that due to the USB_DEVICE_INFO(0xe0, 0x01, 0x01) matching
rule we need to actually blacklist all vendor drivers in btusb.ko anyway
and thus a simple BTUSB_IGNORE now turns into something nasty like
declaring a btusb_driver_info struct. I rather avoid that.
It is actually pretty important that a public exported btusb_probe()
really only does what we would expect from a default H:2 probe handler
and not any quirk handling. The existing quirks are internal to btusb.ko
and should not be inherited by any vendor driver.
So btusb_driver struct can easily use a btusb_probe_one() function that
does the quirk handling and then call btusb_probe(). Or just something
similar to that extend.
Bottom line, please do not make the code more complicated because it
looks easy now. It will backfire at some point. We need to make handling
vendor drivers easier by keeping the core H:2 driver simple.
Another option here is to have some convenience macros like
BTUSB_DEVICE_IGNORE(0x0a5c, 0x2033) that turn the code readable again.
And while you are at it, please split the mini-driver support changes
from actually modifying the HCI core. I like to have this as two
patches.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH v3 06/10] sbc: Add mmx primitive for 1b 8s analyse
From: Siarhei Siamashka @ 2012-10-27 23:29 UTC (permalink / raw)
To: Siarhei Siamashka; +Cc: Frédéric Dalleau, linux-bluetooth
In-Reply-To: <20121028020621.3653ac8e@i7>
On Sun, 28 Oct 2012 02:06:21 +0300
Siarhei Siamashka <siarhei.siamashka@gmail.com> wrote:
> On Fri, 26 Oct 2012 19:20:32 +0200
> Frédéric Dalleau <frederic.dalleau@linux.intel.com> wrote:
>
> > ---
> > sbc/sbc_primitives_mmx.c | 18 +++++++++++++++++-
> > 1 file changed, 17 insertions(+), 1 deletion(-)
>
> In the previous patches you are changing the behaviour of C
> implementation to support mSBC configuration. By still allowing
> assembly optimized implementations to override C functions, mSBC
> does not work correctly for the architectures which support these
> optimizations.
>
> With this particular patch you are fixing MMX. The other
> implementations (ARM NEON) are still broken.
>
> It would be better if we could shape out this patch series so that
> the code is always correct after every commit, preferably as:
> 1. SBC still works and uses assembly optimizations after
> every commit
> 2. mSBC works correctly after the commit where SBC_MSBC feature
> is advertised in the public header "sbc.h"
> 3. mSBC gets assembly optimizations enabled. Unsupported architectures
> use C implementation.
Just to make this work, your "[PATCH v3 04/10] sbc: Add msbc flag and
generic C primitive" patch could update "sbc_init_primitives" in a
bit different way.
You changed it as:
> void sbc_init_primitives(struct sbc_encoder_state *state)
> {
> + state->pending = -1;
> + state->odd = 1;
> +
> /* Default implementation for analyze functions */
> state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_simd;
> - state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
> +
> + if (state->increment == 1)
> + state->sbc_analyze_4b_8s = sbc_analyze_1b_8s_simd;
> + else
> + state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
But it might be better to move "if (state->increment == 1)" check to
the very end of the function after
/* X86/AMD64 optimizations */
#ifdef SBC_BUILD_WITH_MMX_SUPPORT
sbc_init_primitives_mmx(state);
#endif
/* ARM optimizations */
#ifdef SBC_BUILD_WITH_ARMV6_SUPPORT
sbc_init_primitives_armv6(state);
#endif
#ifdef SBC_BUILD_WITH_IWMMXT_SUPPORT
sbc_init_primitives_iwmmxt(state);
#endif
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
sbc_init_primitives_neon(state);
#endif
So that the C implementation overrides the function pointers for
mSBC configuration after the initialization of mSBC-unaware assembly
implementations.
As soon as some assembly implementation gets mSBC support (MMX for
example), the initialization order in "sbc_init_primitives" can be
changed appropriately.
--
Best regards,
Siarhei Siamashka
^ permalink raw reply
* Re: [RFC v1 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse
From: Michał Poczwardowski @ 2012-10-27 23:24 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <CABBYNZ+T1hAonu-05UELbzthnNS=8CXHSKYRN1p+wWvm37ePXQ@mail.gmail.com>
Hello,
On 26 October 2012 16:14, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Fri, Oct 26, 2012 at 4:10 PM, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>> Hi Michal,
>>
>> On Sun, Oct 21, 2012 at 7:05 PM, Michał Poczwardowski
>> <dmp0x7c5@gmail.com> wrote:
>>> ---
>>> fuse/helpers.c | 55 +++++++++++++++++++++++++
>>> fuse/helpers.h | 49 ++++++++++++++++++++++
>>> fuse/obexfuse.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 223 insertions(+), 0 deletions(-)
>>> create mode 100644 fuse/helpers.c
>>> create mode 100644 fuse/helpers.h
>>> create mode 100644 fuse/obexfuse.c
>>>
>>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>>> new file mode 100644
>>> index 0000000..53bba57
>>> --- /dev/null
>>> +++ b/fuse/helpers.c
>>> @@ -0,0 +1,55 @@
>>> +/*
>>> + * OBEX Filesystem in Userspace
>>> + *
>>> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
>>> + *
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>>> + *
>>> + */
>>> +
>>> +#include <gobex/gobex.h>
>>> +#include <btio/btio.h>
>>> +
>>> +#include <glib.h>
>>> +#include <fcntl.h>
>>> +#include <errno.h>
>>> +
>>> +#include <bluetooth/bluetooth.h>
>>> +#include <bluetooth/rfcomm.h>
>>> +#include <bluetooth/sdp.h>
>>> +#include <bluetooth/sdp_lib.h>
>>> +
>>> +#define BT_RX_MTU 32767
>>> +#define BT_TX_MTU 32767
>>> +
>>> +#include "helpers.h"
>>> +
>>> +#define OBEX_FTP_UUID \
>>> + "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
>>> +#define OBEX_FTP_UUID_LEN 16
>>> +
>>> +#define OBEX_FTP_LS "x-obex/folder-listing"
>>> +
>>> +struct gobexhlp_request {
>>> + gchar *name;
>>> + gboolean complete;
>>> +};
>>> +
>>> +struct gobexhlp_location {
>>> + gchar *dir;
>>> + gchar *file;
>>> +};
>>> +
>>> diff --git a/fuse/helpers.h b/fuse/helpers.h
>>> new file mode 100644
>>> index 0000000..21972b2
>>> --- /dev/null
>>> +++ b/fuse/helpers.h
>>> @@ -0,0 +1,49 @@
>>> +/*
>>> + * OBEX Filesystem in Userspace
>>> + *
>>> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
>>> + *
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>>> + *
>>> + */
>>> +
>>> +#include <gobex/gobex.h>
>>> +#include <glib.h>
>>> +
>>> +struct gobexhlp_request;
>>> +
>>> +struct gobexhlp_buffer {
>>> + void *data;
>>> + gsize tmpsize;
>>> + gsize size;
>>> + gboolean edited;
>>> +};
>>> +
>>> +struct gobexhlp_session {
>>> + GObex *obex;
>>> + GList *lsfiles;
>>> + GIOChannel *io;
>>> + GHashTable *file_stat;
>>> + gchar *setpath;
>>> + struct gobexhlp_request *request;
>>> + struct gobexhlp_buffer *buffer;
>>> + gboolean vtouch;
>>> + gchar *vtouch_path;
>>> + gboolean rtouch;
>>> + int status;
>>> + GError *err;
>>> +};
>>> +
>>> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
>>> new file mode 100644
>>> index 0000000..fe4f4da
>>> --- /dev/null
>>> +++ b/fuse/obexfuse.c
>>> @@ -0,0 +1,119 @@
>>> +/*
>>> + * OBEX Filesystem in Userspace
>>> + *
>>> + * Copyright (C) 2012 Michał Poczwardowski <dmp0x7c5@gmail.com>
>>> + *
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>>> + *
>>> + */
>>> +
>>> +#define FUSE_USE_VERSION 26
>>> +
>>> +#include <stdio.h>
>>> +#include <errno.h>
>>> +#include <fcntl.h>
>>> +#include <stdlib.h>
>>> +#include <string.h>
>>> +
>>> +#include <fuse.h>
>>> +#include <fuse/fuse_opt.h>
>>> +
>>> +#include "helpers.h"
>>> +
>>> +struct options {
>>> + char* dststr;
>>> + char* srcstr;
>>> +} options;
>>> +
>>> +#define GOBEXFUSE_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v }
>>> +
>>> +enum
>>> +{
>>> + KEY_VERSION,
>>> + KEY_HELP,
>>> +};
>>> +
>>> +static struct fuse_opt obexfuse_opts[] =
>>> +{
>>> + GOBEXFUSE_OPT_KEY("--target=%s",dststr, 0),
>>> + GOBEXFUSE_OPT_KEY("-t %s", dststr, 0),
>>> + GOBEXFUSE_OPT_KEY("--source=%s",srcstr, 0),
>>> + GOBEXFUSE_OPT_KEY("-s %s", srcstr, 0),
>>> +
>>> + FUSE_OPT_KEY("-V", KEY_VERSION),
>>> + FUSE_OPT_KEY("--version", KEY_VERSION),
>>> + FUSE_OPT_KEY("-h", KEY_HELP),
>>> + FUSE_OPT_KEY("--help", KEY_HELP),
>>> + FUSE_OPT_END
>>> +};
>>> +
>>> +static struct fuse_operations obexfuse_oper = {
>>> +};
>>> +
>>> +static int obexfuse_opt_proc(void *data, const char *arg, int key,
>>> + struct fuse_args *outargs)
>>> +{
>>> + switch (key) {
>>> + case KEY_HELP:
>>> + g_printerr("Usage: %s mountpoint [options]\n"
>>> + "\n"
>>> + "general options:\n"
>>> + " -o opt,[opt...] mount options\n"
>>> + " -h --help print help\n"
>>> + " -V --version print version\n"
>>> + "\n"
>>> + "obexfuse options:\n"
>>> + " -t --target target btaddr "
>>> + "(mandatory)\n"
>>> + " -s --source source btaddr\n"
>>> + "\n"
>>> + , outargs->argv[0]);
>>> + fuse_opt_add_arg(outargs, "-ho");
>>> + fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
>>> + exit(1);
>>> + case KEY_VERSION:
>>> + g_print("obexfuse upon:\n");
>>> + fuse_opt_add_arg(outargs, "--version");
>>> + fuse_main(outargs->argc, outargs->argv, &obexfuse_oper, NULL);
>>> + exit(0);
>>> + }
>>> + return 1;
>>> +}
>>> +
>>> +int main(int argc, char *argv[])
>>> +{
>>> + int retfuse;
>>> + struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
>>> +
>>> + memset(&options, 0, sizeof(struct options));
>>> +
>>> + if (fuse_opt_parse(&args, &options, obexfuse_opts,
>>> + obexfuse_opt_proc) == -1)
>>> + return -EINVAL;
>>> +
>>> + if (options.dststr == NULL) {
>>> + g_printerr("Target not specified\n");
>>> + return -EINVAL;
>>> + }
>>> +
>>> + g_thread_init(NULL);
>>> +
>>> + fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
>>> + retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
>>> +
>>> + fuse_opt_free_args(&args);
>>> + return retfuse;
>>> +}
>>> --
>>> 1.7.8.6
>>
>> Doesn't apply:
>>
>> Applying: fuse: Add initial obexfuse files, fuse main and options parse
>> /home/vudentz/git/obexd/.git/rebase-apply/patch:70: new blank line at EOF.
>> +
>> /home/vudentz/git/obexd/.git/rebase-apply/patch:125: new blank line at EOF.
>> +
>> fatal: 2 lines add whitespace errors.
>> Patch failed at 0001 fuse: Add initial obexfuse files, fuse main and
>> options parse
>
> Somehow patch 01 seems to mangled, it has windows style line break and
> git doesn't like that.
>
>
> --
> Luiz Augusto von Dentz
Sorry for that "new blank line at EOF". I'll fix my patches. I didn't
run gif diff --check to spot this.
Regarding windows line break, I swear that windows has never even seen
my code :)
Thanks,
Michal
^ permalink raw reply
* Re: [PATCH v3 06/10] sbc: Add mmx primitive for 1b 8s analyse
From: Siarhei Siamashka @ 2012-10-27 23:06 UTC (permalink / raw)
To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <1351272036-4875-7-git-send-email-frederic.dalleau@linux.intel.com>
On Fri, 26 Oct 2012 19:20:32 +0200
Frédéric Dalleau <frederic.dalleau@linux.intel.com> wrote:
> ---
> sbc/sbc_primitives_mmx.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
In the previous patches you are changing the behaviour of C
implementation to support mSBC configuration. By still allowing
assembly optimized implementations to override C functions, mSBC
does not work correctly for the architectures which support these
optimizations.
With this particular patch you are fixing MMX. The other
implementations (ARM NEON) are still broken.
It would be better if we could shape out this patch series so that
the code is always correct after every commit, preferably as:
1. SBC still works and uses assembly optimizations after
every commit
2. mSBC works correctly after the commit where SBC_MSBC feature
is advertised in the public header "sbc.h"
3. mSBC gets assembly optimizations enabled. Unsupported architectures
use C implementation.
> diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
> index cbacb4e..17065e5 100644
> --- a/sbc/sbc_primitives_mmx.c
> +++ b/sbc/sbc_primitives_mmx.c
> @@ -276,6 +276,19 @@ static inline void sbc_analyze_4b_8s_mmx(struct sbc_encoder_state *state,
> __asm__ volatile ("emms\n");
> }
>
> +static inline void sbc_analyze_1b_8s_mmx(struct sbc_encoder_state *state,
> + int16_t *x, int32_t *out, int out_stride)
> +{
> + if (state->odd)
> + sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_odd);
> + else
> + sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_even);
> +
> + state->odd = !state->odd;
> +
> + __asm__ volatile ("emms\n");
> +}
> +
> static void sbc_calc_scalefactors_mmx(
> int32_t sb_sample_f[16][2][8],
> uint32_t scale_factor[2][8],
> @@ -366,7 +379,10 @@ void sbc_init_primitives_mmx(struct sbc_encoder_state *state)
> {
> if (check_mmx_support()) {
> state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_mmx;
> - state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_mmx;
> + if (state->increment == 1)
> + state->sbc_analyze_4b_8s = sbc_analyze_1b_8s_mmx;
Overriding the function with "_4b_" (4 blocks) in its name with "_1b_"
variant (1 block) looks wrong and is just asking for troubles.
Maybe we need a new function pointer? If not, then the function might
need to be at least renamed.
> + else
> + state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_mmx;
> state->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
> state->implementation_info = "MMX";
> }
--
Best regards,
Siarhei Siamashka
^ permalink raw reply
* Re: [PATCH v3 04/10] sbc: Add msbc flag and generic C primitive
From: Siarhei Siamashka @ 2012-10-27 22:19 UTC (permalink / raw)
To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <1351272036-4875-5-git-send-email-frederic.dalleau@linux.intel.com>
On Fri, 26 Oct 2012 19:20:30 +0200
Frédéric Dalleau <frederic.dalleau@linux.intel.com> wrote:
> ---
> sbc/sbc.c | 27 +++++++++++++++------
> sbc/sbc.h | 3 +++
> sbc/sbc_primitives.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
> sbc/sbc_primitives.h | 2 ++
> 4 files changed, 88 insertions(+), 10 deletions(-)
Maybe it would be a bit cleaner to split this a bit?
I mean a separate patch for the part, which extends
"sbc_encoder_process_input_s8" function to support 8 samples
granularity for "nsamples" argument (down from 16 samples
granularity for "nsamples" in the current code).
> diff --git a/sbc/sbc.c b/sbc/sbc.c
> index 9b0634d..4bc97fc 100644
> --- a/sbc/sbc.c
> +++ b/sbc/sbc.c
> @@ -52,6 +52,9 @@
>
> #define SBC_SYNCWORD 0x9C
>
> +#define MSBC_SYNCWORD 0xAD
> +#define MSBC_BLOCKS 15
> +
> /* This structure contains an unpacked SBC frame.
> Yes, there is probably quite some unused space herein */
> struct sbc_frame {
> @@ -705,6 +708,10 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
> for (ch = 0; ch < frame->channels; ch++) {
> x = &state->X[ch][state->position - 8 * state->increment +
> frame->blocks * 8];
> +
> + if (state->pending == state->position)
> + x += 8;
The use of both "state->pending" and "state->position" outside
"sbc_encoder_process_input_s8" function looks a bit messy. It's kind
of like exposing its internal implementation detail unnecessarily.
> for (blk = 0; blk < frame->blocks; blk += state->increment) {
> state->sbc_analyze_4b_8s(
> state, x,
> @@ -901,12 +908,12 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
> }
> }
>
> -static void sbc_encoder_init(struct sbc_encoder_state *state,
> - const struct sbc_frame *frame)
> +static void sbc_encoder_init(unsigned long flags,
> + struct sbc_encoder_state *state, const struct sbc_frame *frame)
> {
> memset(&state->X, 0, sizeof(state->X));
> state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
> - state->increment = 4;
> + state->increment = flags & SBC_MSBC ? 1 : 4;
>
> sbc_init_primitives(state);
> }
> @@ -920,6 +927,7 @@ struct sbc_priv {
>
> static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
> {
> + sbc->flags = flags;
> sbc->frequency = SBC_FREQ_44100;
> sbc->mode = SBC_MODE_STEREO;
> sbc->subbands = SBC_SB_8;
> @@ -1055,12 +1063,13 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
> priv->frame.subband_mode = sbc->subbands;
> priv->frame.subbands = sbc->subbands ? 8 : 4;
> priv->frame.block_mode = sbc->blocks;
> - priv->frame.blocks = 4 + (sbc->blocks * 4);
> + priv->frame.blocks = sbc->flags & SBC_MSBC ?
> + MSBC_BLOCKS : 4 + (sbc->blocks * 4);
> priv->frame.bitpool = sbc->bitpool;
> priv->frame.codesize = sbc_get_codesize(sbc);
> priv->frame.length = sbc_get_frame_length(sbc);
>
> - sbc_encoder_init(&priv->enc_state, &priv->frame);
> + sbc_encoder_init(sbc->flags, &priv->enc_state, &priv->frame);
> priv->init = 1;
> } else if (priv->frame.bitpool != sbc->bitpool) {
> priv->frame.length = sbc_get_frame_length(sbc);
> @@ -1139,7 +1148,7 @@ SBC_EXPORT size_t sbc_get_frame_length(sbc_t *sbc)
> return priv->frame.length;
>
> subbands = sbc->subbands ? 8 : 4;
> - blocks = 4 + (sbc->blocks * 4);
> + blocks = sbc->flags & SBC_MSBC ? MSBC_BLOCKS : 4 + (sbc->blocks * 4);
> channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
> joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
> bitpool = sbc->bitpool;
> @@ -1163,7 +1172,8 @@ SBC_EXPORT unsigned sbc_get_frame_duration(sbc_t *sbc)
> priv = sbc->priv;
> if (!priv->init) {
> subbands = sbc->subbands ? 8 : 4;
> - blocks = 4 + (sbc->blocks * 4);
> + blocks = sbc->flags & SBC_MSBC ?
> + MSBC_BLOCKS : 4 + (sbc->blocks * 4);
> } else {
> subbands = priv->frame.subbands;
> blocks = priv->frame.blocks;
> @@ -1200,7 +1210,8 @@ SBC_EXPORT size_t sbc_get_codesize(sbc_t *sbc)
> priv = sbc->priv;
> if (!priv->init) {
> subbands = sbc->subbands ? 8 : 4;
> - blocks = 4 + (sbc->blocks * 4);
> + blocks = sbc->flags & SBC_MSBC ?
> + MSBC_BLOCKS : 4 + (sbc->blocks * 4);
> channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
> } else {
> subbands = priv->frame.subbands;
> diff --git a/sbc/sbc.h b/sbc/sbc.h
> index bbd45da..3511119 100644
> --- a/sbc/sbc.h
> +++ b/sbc/sbc.h
> @@ -64,6 +64,9 @@ extern "C" {
> #define SBC_LE 0x00
> #define SBC_BE 0x01
>
> +/* Additional features */
> +#define SBC_MSBC 0x01
> +
> struct sbc_struct {
> unsigned long flags;
>
> diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
> index 7ba0589..47caf11 100644
> --- a/sbc/sbc_primitives.c
> +++ b/sbc/sbc_primitives.c
> @@ -209,6 +209,17 @@ static inline void sbc_analyze_4b_8s_simd(struct sbc_encoder_state *state,
> sbc_analyze_eight_simd(x + 0, out, analysis_consts_fixed8_simd_even);
> }
>
> +static inline void sbc_analyze_1b_8s_simd(struct sbc_encoder_state *state,
> + int16_t *x, int32_t *out, int out_stride)
> +{
> + if (state->odd)
> + sbc_analyze_eight_simd(x, out, analysis_consts_fixed8_simd_odd);
> + else
> + sbc_analyze_eight_simd(x, out, analysis_consts_fixed8_simd_even);
> +
> + state->odd = !state->odd;
> +}
> +
> static inline int16_t unaligned16_be(const uint8_t *ptr)
> {
> return (int16_t) ((ptr[0] << 8) | ptr[1]);
> @@ -298,8 +309,25 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
> #define PCM(i) (big_endian ? \
> unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
>
> + if (state->pending >= 0) {
> + state->pending = -1;
> + nsamples -= 8;
> + if (nchannels > 0) {
> + int16_t *x = &X[0][position];
> + x[0] = PCM(0 + (15-8) * nchannels);
> + x[2] = PCM(0 + (14-8) * nchannels);
> + x[3] = PCM(0 + (8-8) * nchannels);
> + x[4] = PCM(0 + (13-8) * nchannels);
> + x[5] = PCM(0 + (9-8) * nchannels);
> + x[6] = PCM(0 + (12-8) * nchannels);
> + x[7] = PCM(0 + (10-8) * nchannels);
> + x[8] = PCM(0 + (11-8) * nchannels);
> + }
Here it would be nice to have a comment in the code about why
the same processing is skipped for nchannels > 1.
And because the code is becoming even more complex, more detailed
comments describing "sbc_encoder_process_input" would be a great
addition (the usage constraints, the expected input, the expected
output).
> + pcm += 16 * nchannels;
> + }
> +
> /* copy/permutate audio samples */
> - while ((nsamples -= 16) >= 0) {
> + while (nsamples >= 16) {
> position -= 16;
> if (nchannels > 0) {
> int16_t *x = &X[0][position];
> @@ -340,6 +368,33 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
> x[15] = PCM(1 + 2 * nchannels);
> }
> pcm += 32 * nchannels;
> + nsamples -= 16;
> + }
> +
> + if (nsamples == 8) {
> + position -= 16;
> + state->pending = position;
If "position" was not decremented by 16 for 8 samples here, then you
would not need to do
if (state->pending == state->position)
x += 8;
elsewhere.
Maybe "state->pending" variable can be removed altogether and
just replaced by the checks whether "state->position" is divisible
by 16 or not? The "move old samples on wraparound" code may need to
be updated to ensure that this divisibility by 16 check is not
messed up.
> +
> + if (nchannels > 0) {
> + int16_t *x = &X[0][position];
> + x[0] = 0;
> + x[1] = PCM(0 + 7 * nchannels);
> + x[2] = 0;
> + x[3] = 0;
> + x[4] = 0;
> + x[5] = 0;
> + x[6] = 0;
> + x[7] = 0;
> + x[8] = 0;
The initialization to 0 looks redundant to me. The samples from
the future (which are not yet available to the encoder at this
moment) are not supposed to have any effect on calculations. They
should be quite conveniently multiplied by zero constants in the
analysis filter and cancelled out. If they did affect anything, this
would indicate a serious bug in the codec.
> + x[9] = PCM(0 + 3 * nchannels);
> + x[10] = PCM(0 + 6 * nchannels);
> + x[11] = PCM(0 + 0 * nchannels);
> + x[12] = PCM(0 + 5 * nchannels);
> + x[13] = PCM(0 + 1 * nchannels);
> + x[14] = PCM(0 + 4 * nchannels);
> + x[15] = PCM(0 + 2 * nchannels);
> + }
> + pcm += 16 * nchannels;
> }
> #undef PCM
One more nitpick about "sbc_encoder_process_input_s8". The old
variant was taking "position" as a function argument and returning
an updated position.
After you changes, the position is now read from the "state" struct in
the beginning of the function. It looks a bit ugly to still return
the updated position value from the function and expect the caller to
store it back to the "state" struct.
> @@ -523,9 +578,16 @@ static int sbc_calc_scalefactors_j(
> */
> void sbc_init_primitives(struct sbc_encoder_state *state)
> {
> + state->pending = -1;
> + state->odd = 1;
> +
> /* Default implementation for analyze functions */
> state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_simd;
> - state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
> +
> + if (state->increment == 1)
> + state->sbc_analyze_4b_8s = sbc_analyze_1b_8s_simd;
> + else
> + state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
>
> /* Default implementation for input reordering / deinterleaving */
> state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
> diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
> index eed946e..9a27d3c 100644
> --- a/sbc/sbc_primitives.h
> +++ b/sbc/sbc_primitives.h
> @@ -40,6 +40,8 @@ struct sbc_encoder_state {
> int position;
> /* Number of consecutive blocks handled by the encoder */
> int increment;
> + int pending;
> + int odd;
> int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
> /* Polyphase analysis filter for 4 subbands configuration,
> * it handles "increment" blocks at once */
--
Best regards,
Siarhei Siamashka
^ permalink raw reply
* [PATCH] Bluetooth: Add support for BCM20702A0 [0b05, 17b5]
From: Jeff Cook @ 2012-10-27 11:01 UTC (permalink / raw)
To: linux-bluetooth, marcel, gustavo, johan.hedberg; +Cc: linux-kernel, Jeff Cook
In-Reply-To: <5087B517.9090703@deserettechnology.com>
Vendor-specific ID for BCM20702A0.
Support for bluetooth over Asus Wi-Fi GO!, included with Asus P8Z77-V
Deluxe.
T: Bus=07 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0b05 ProdID=17b5 Rev=01.12
S: Manufacturer=Broadcom Corp
S: Product=BCM20702A0
S: SerialNumber=94DBC98AC113
C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none)
I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
Signed-off-by: Jeff Cook <jeff@deserettechnology.com>
---
drivers/bluetooth/btusb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 654e248..1d7b126 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
--
1.8.0
^ 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