Block Device Drivers

I am new to drivers development under linux kernel. After starting with the simple examples from the book Linux Device Drivers v3, I realised that the block driver API has been totally changed since the kernel 2.6.31 or maybe later versions, and I couldn't find any documentation about the new API and how to use it. There are just some few comments in the source code.

After struggling for one month I almost had something working but few parts are missing or I misunderstood something.

Here is the situation :

After fetching the request with blk_fetch_request(q), I use the macro __rq_for_each_bio for handling the full request
To transfer the segments one by one I use the macro bio_for_each_segment(bvec, bio, i) that loops over all the segments in a bio

My question is :

I need to do some DMA from/to my device (the dma engine is within the device), that's why I need some address that I could use it to DMA from/to
Which buffer should I use ? for the moment I use the buffer returned by char *buffer=bio_data(bio), Does "buffer" corresponds to the physical buffer that I can use for DMA
How to end the request in this case ? using __blk_end_request_cur(req, 0) ? or using __blk_end_request(req, 0, bytes) ?

If you don't have an answer to any of these questions, where can I find a useful documentation for the new API of the block device drivers.


Similar Content



What Are The Differences Between Character Devices And Block Devices?

Hi,

I am trying to understand the difference between char devices and block devices.
I understand the basic, which is that char devices input/output data one character at a time, whereas block device input/output data block by block. But for char device driver, most of the time we are able to read/write an array of data using the read/write system call. This "array of data" sounds like a block of data to me, except that it's not fixed in size as for block devices. With this thinking, can I say that I can effectively achieve block read/write with a char device driver?
And what are the other differences?

Thank you all,
Wei

I Need To Increase Keyboard Buffer Size To Allow Key Strokes At 6000 WPM

I am using Debian 7 KVM in a cloud and I find the keyboard buffer in a terminal window is about 35 characters in length thus when I run my keyboard emulator, I have to pause after 35 keys in order not to overflow the buffer.

I want to be able to login and dump the instructions to the KVM server then go to the next one. e.g If I wanted a mass roll out of Yacy search engines or other applications.

I know no Human can type that fast. But my Program can on the PS2 interface.
The USB keyboard port maxes out a 700 WPM
over 5000 Word Per Minute

Double TtyACM Node Device From Sony Ericsson C510

Hi.


I'm using smstools3 and Sony Ericsson Phones to send SMS. My system did work well with 4 phones, now I want to connect 20.
The issue is that each phone generates two ttyACMXX devices using cdc_acm driver, and for limitations the driver supports up to 32 ACM devices

Code:
Aug 31 09:51:19 smsgw kernel: cdc_acm 2-2:1.1: ttyACM31: USB ACM device
Aug 31 09:51:19 smsgw kernel: cdc_acm 2-2:1.3: ttyACM32: USB ACM device
Aug 31 09:51:19 smsgw kernel: usbco  registered new driver cdc_acm
Aug 31 09:51:19 smsgw kernel: drivers/usb/class/cdc-acm.c: v0.25:USB Abstract Control Model driver for USB modems and ISDN adapters
Aug 31 09:51:19 smsgw kernel: usbco  registered new driver cdc_ether
Aug 31 09:51:19 smsgw kernel: usb 2-2: unsupported MDLM descriptors
Aug 31 09:52:01 smsgw kernel: cdc_acm 3-1:1.0: no more free acm devices

From the ttyACM devices created by the driver I only use the first one..

So I was wondering if it is possible to remove a ttyACM from /sys/class/tty/ttyACM1

I tried unlink /dev/ttyACM1, but it persist as a device on /sys/class/tty/

The devices are removed if I disconnect the phone, So I think would be possible also that the driver only create one ttyACM device..

Please guide me...

Thanks in advance.

Record Buffer Provided By Awk

we do have a record buffer in awk utility that holds one complete record of a data file.

I want to know that if record buffer changes during script processing, then when are these changes reflected back to the data file?

Are they reflected immediately or is there an in-built mechanism available to schedule this change?

Is It Time For A Modem Funeral?

I have a USB fax modem, and it logs the following errors when turned on.

I know it is impossible to know for sure, but think it is hardware related? Any chance to salvage?

Also, what are the steps to start troubleshooting?

Thanks

Code:
Jan 17 14:38:26 devserver kernel: generic-usb 0003:0461:4D0F.0066: input,hidraw2: USB HID v1.11 Mouse [PixArt USB Optical Mouse] on usb-0000:00:1a.0-1.2/input0
Jan 17 14:38:41 devserver kernel: usb 3-1: new full speed USB device number 24 using xhci_hcd
Jan 17 14:38:41 devserver kernel: usb 3-1: device descriptor read/all, error -71
Jan 17 14:38:41 devserver kernel: usb 3-1: new full speed USB device number 25 using xhci_hcd
Jan 17 14:38:41 devserver kernel: usb 3-1: device descriptor read/all, error -71
Jan 17 14:38:41 devserver kernel: usb 3-1: new full speed USB device number 26 using xhci_hcd
Jan 17 14:38:41 devserver kernel: usb 3-1: device descriptor read/8, error -71
Jan 17 14:38:41 devserver kernel: usb 3-1: device descriptor read/8, error -71
Jan 17 14:38:41 devserver kernel: usb 3-1: new full speed USB device number 27 using xhci_hcd
Jan 17 14:38:41 devserver kernel: usb 3-1: device descriptor read/8, error -71
Jan 17 14:38:42 devserver kernel: usb 3-1: device descriptor read/8, error -71
Jan 17 14:38:42 devserver kernel: hub 3-0:1.0: unable to enumerate USB device on port 1

Ubuntu Studio + M-Audio Drivers

Hi there folks, first post and been using Linux for roughly a week, not an expert but getting the feel for it.

So....my question is: I am in the process of building a studio-rig for music, and previoulsy I used Windows, and managed to get the x64 drivers for my audio card the Delta 1010LT and got it working etc. It came with the control panel as well.

I tried googling for the drivers for Ubuntu Studio (64), but to be honest, like I said being a newbie, I'm not entirely sure I have to download them? Most things I can just request download and install from the terminal in Ubuntu. Does this apply for these drivers or if not does anyone know the location of these drivers?

Much help is appreciated

Fritz! WLAN USB Stick N V2 - NDISWRAPPER Problem

Hi guys,

I'm new to the forum and the first problem appeared, hope u guys can help me out!


Just changed my system from Windows to Linux and have some issues to get my Wifi Stick
Fritz! WLAN USB N v 2 working.

1. I downloaded the newest drivers for Win64-Bit from the AVM Homepage.
2. Started ndiswrapper Selected the fwlan64.inf -> Clicked on install.
3. Error Message appears :
modprobe: FATAL: Module ndiswrapper not found
4. Uninstalled ndiswrapper (thought probably and older version could fix this was reading on some Ubuntu Forum cause i couldnt find anything for Ziron)

Any help appreciated!

Thank you so much!

Edit: Some more info

System Log:

Quote:
stani-System-Product-Name kernel: [ 2085.487551] usb 2-1.6: USB disconnect, device number 13
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.452762] usb 2-1.6: new high-speed USB device number 14 using ehci-pci
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.549669] usb 2-1.6: New USB device found, idVendor=057c, idProduct=8501
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.549674] usb 2-1.6: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.549677] usb 2-1.6: Product: FRITZ!WLAN USB Stick N v2
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.549680] usb 2-1.6: Manufacturer: AVM Berlin
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.549682] usb 2-1.6: SerialNumber: 246511430F18
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.624607] usb 2-1.6: reset high-speed USB device number 14 using ehci-pci
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.719007] ieee80211 phy4: rt2x00_set_rt: Info - RT chipset 5592, rev 0222 detected
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.756314] ieee80211 phy4: rt2x00usb_vendor_request: Error - Vendor Request 0x09 failed for offset 0x0000 with error -32
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.756320] ieee80211 phy4: rt2x00lib_probe_dev: Error - Failed to allocate device
Feb 12 16:34:23 stani-System-Product-Name kernel: [ 2086.756349] rt2800usb: probe of 2-1.6:1.0 failed with error -32
Feb 12 16:34:23 stani-System-Product-Name mtp-probe: checking bus 2, device 14: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.6"
Feb 12 16:34:23 stani-System-Product-Name mtp-probe: bus: 2, device: 14 was not an MTP device
Feb 12 16:34:24 stani-System-Product-Name usb_modeswitch: switched to 057c:ffffffff on 002/013
uname -a

Quote:
Linux stani-System-Product-Name 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
stani@stani-System-Product-Name:~$
lsusb
Quote:
Bus 002 Device 006: ID 0b05:179c ASUSTek Computer, Inc.
Bus 002 Device 014: ID 057c:8501 AVM GmbH
Bus 002 Device 004: ID 1ea7:1005
Bus 002 Device 003: ID 046d:c326 Logitech, Inc.
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 002: ID 05e3:0727 Genesys Logic, Inc. microSD Reader/Writer
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Error In Running Leach_test In NS-2.34

Hi all,

I am trying to simulate leach on NS2 but I've had problems with running the leach_test. I've followed all steps from installing NS2 up to installing the LEACH patch (used the latest one from exidus). Here's the error message in the leach.err I found.

Code:
couldn't read file "/mit/uAMPS/uamps.tcl": no such file or directory
    while executing
"source.orig /mit/uAMPS/uamps.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel source.orig[list $fileName]"
    invoked from within
"if [$instance_ is_http_url $fileName] {
set buffer [$instance_ read_url $fileName]
uplevel eval $buffer
} else {
uplevel source.orig[list $fileName]
..."
    (procedure "source" line 8)
    invoked from within
"source /mit/uAMPS/uamps.tcl"
    (file "tcl/mobility/leach.tcl" line 18)
    invoked from within
"source.orig tcl/mobility/leach.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel source.orig[list $fileName]"
    invoked from within
"if [$instance_ is_http_url $fileName] {
set buffer [$instance_ read_url $fileName]
uplevel eval $buffer
} else {
uplevel source.orig[list $fileName]
..."
    (procedure "source" line 8)
    invoked from within
"source tcl/mobility/$opt(rp).tcl"
    (file "tcl/ex/wireless.tcl" line 187)

Your help are very much appreciated, thanks!

Help To Disperse The Data Using Bitsplitter

I am totally new to Linux. I am working on Nubisave project in TU Dresden. I am stuck in running the C program. Its bitsplitter program. Can anybody help me out? should I post the program here? Will it be helpful for me? I knnow little basics of C language and the code is totally new for me.
I have used the code of bitsplitter and it is running but I am not understanding the output. This is code from Tu Dresden. Can anybody explain me how it is working?

#include "bitsplit.h"

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <stdlib.h>
#include <string.h>

#define SPLITDEBUG 0

struct fillbyte_t {
char *bits;
int bitctr;
char bytes[1024];
int bytectr;
unsigned char numbits;
unsigned char shiftbits;
unsigned int pattern;
FILE *f;
char *buffer;
ssize_t bufferctr;
};
typedef struct fillbyte_t fillbyte;

struct bitsplit_t {
fillbyte *b;
int parts;
int redundant;
int totalbits;
};
typedef struct bitsplit_t bitsplit;

static void bitsplitfinish(bitsplit bs)
{
int j;

for(j = 0; j < (bs.parts + bs.redundant); j++)
{
if(bs.b[j].f)
fclose(bs.b[j].f);
free(bs.b[j].bits);
/*free(bs.b[j].buffer);*/ /* the caller clears this */
}
free(bs.b);
bs.b = NULL;
}

static bitsplit bitsplitprepare(const char *directory, int parts, int redundant, int bitwidth)
{
fillbyte *b;
bitsplit bs;
int ret;
char fname[1024];
int sumbits, totalbits;
int i, j;

bs.b = NULL;

if(directory)
{
ret = mkdir(directory, S_IRWXU);
if((ret != 0) && (errno != EEXIST)) return bs;
}

b = malloc((parts + redundant) * sizeof(fillbyte));
for(j = 0; j < (parts + redundant); j++)
{
b[j].bitctr = 0;
b[j].bytectr = 0;
b[j].buffer = NULL;
b[j].bufferctr = 0;
if(directory)
{
snprintf(fname, sizeof(fname), "%s/%i.stream", directory, j);
b[j].f = fopen(fname, "w");
}
else b[j].f = NULL;
}

sumbits = 0;
totalbits = (int)(((parts - 1) / bitwidth) + 1) * bitwidth;
#if SPLITDEBUG
printf("bitwidth: %i; totalbits: %i\n", bitwidth, totalbits);
#endif

if(redundant)
if(totalbits % parts != 0)
{
bitsplitfinish(bs);
return bs;
}

for(j = parts - 1; j >= 0; j--)
{
b[j].bits = (char*)malloc(totalbits * 8 * sizeof(char));

b[j].numbits = (int)((totalbits - sumbits) / (j + 1));
b[j].pattern = 0;
for(i = sumbits; i < sumbits + b[j].numbits; i++)
b[j].pattern |= (1 << i);
b[j].shiftbits = sumbits;
sumbits += b[j].numbits;
#if SPLITDEBUG
printf("bits: fragment %i=%i, pattern=%u\n", j, b[j].numbits, b[j].pattern);
#endif
}
for(j = parts; j < parts + redundant; j++)
{
b[j].bits = (char*)malloc(totalbits * 8 * sizeof(char));
}

bs.b = b;
bs.parts = parts;
bs.redundant = redundant;
bs.totalbits = totalbits;

return bs;
}

static int bitjoinwork(const char **inbuffers, ssize_t *insizes, bitsplit bs)
{
ssize_t i;
int j, k;
int target, revtarget;
int topk, topkcandidate;
int outbits;
int shifted;
int smallest;
int rels[16];
int inshift;

outbits = 8;
shifted = 0;

int xspecial = 0;

xspecial = 1;
if(bs.totalbits > 2 * bs.parts)
xspecial = 0;
if(xspecial)
for(j = 0; j < bs.parts; j++)
if(bs.b[j].numbits > 8) xspecial = 0;
if((bs.parts == 2) && (bs.totalbits == 11))
xspecial = 1;

if((!xspecial) && (bs.totalbits > 8))
outbits = 16;

topk = 0;
for(j = 0; j < bs.parts; j++)
{
topkcandidate = (int)((float)outbits / bs.b[j].numbits) - 1;
if(topkcandidate > topk)
topk = topkcandidate;
}
for(j = 0; j < bs.parts; j++)
{
rels[j] = (int)((topk + 1) / (outbits / bs.b[j].numbits));
// FIXME: mostly untested: =2, *=2 etc. yields 89 OKs
if((!xspecial) && (bs.totalbits > 8))
rels[j] = 2;
if(bs.b[j].numbits == 4)
{
if((bs.parts == 2) && (bs.totalbits == 9))
{
rels[j] = 1;
topk = 1;
}
}
#if SPLITDEBUG
printf("REL/%i=%i <<%i>>\n", j, rels[j], outbits);
#endif
}

smallest = (int)(insizes[0] / rels[0]);
if(((int)(float)insizes[0] * 2 / rels[0]) != smallest * 2)
smallest++;

inshift = (outbits - (topk + 1) * bs.b[0].numbits) % outbits;

int special = 0;
if((bs.parts == 2) && (bs.totalbits > 8))
special = 1;
int special2 = 0;
if((bs.parts == 2) && (bs.totalbits == 5))
special2 = 1;
if((bs.parts == 2) && (bs.totalbits == 7))
special2 = 1;
if((bs.parts == 3) && (bs.totalbits == 7))
special2 = 1;
int special3 = 0;
if((bs.parts == 5) && (bs.totalbits == 15))
special3 = 1;
if((bs.parts == 4) && (bs.totalbits == 12))
special3 = 1;
if((bs.parts == 3) && (bs.totalbits == 9))
special3 = 1;
int special4 = 0;
if((bs.parts == 3) && (bs.totalbits == 15))
special4 = 1;

target = 0;
for(i = 0; i < smallest; i++)
{
#if SPLITDEBUG
printf("- reverse source-pos:%li\n", i);
#endif
// FIXME: special; not for w=14||12, only for w=10!
if((special) && (bs.totalbits == 10) && (shifted >= 10))
{
shifted -= bs.totalbits;
if(shifted < 0)
shifted = 0;
}
#if SPLITDEBUG
printf(" remaining target:%i\n", target);
#endif

for(k = topk; k >= 0; k--)
{
for(j = bs.parts - 1; j >= 0; j--)
{
int packval = (int)(unsigned char)inbuffers[j][i * rels[j]];
// FIXME: read-ahead depends on the relative difference between numbits?
if(rels[j] == 2)
packval = (packval << 8) + (int)(unsigned char)inbuffers[j][i * rels[j] + 1];
// FIXME: special
if((!special) && (!special2) && (!special3) && (!special4))
packval >>= inshift;

int packshift = k * bs.b[j].numbits;
// FIXME: special; only for w=14||12, not for w=10!
if(special)
{
if(bs.b[j].numbits != 4)
packshift = k * 8 - bs.b[j].numbits;
if(bs.totalbits != 10)
packshift += 8;

// for 5+4 bits
if((packshift == 20) && (bs.b[j].numbits == 4))
packshift = 12;
else if((packshift == 16) && (bs.b[j].numbits == 4))
packshift = 8;
else if((packshift == 12) && (bs.b[j].numbits == 4))
packshift = 4;
else if((packshift == 8) && (bs.b[j].numbits == 4))
packshift = 0;
}
if(special2)
{
if((packshift == 9) && (bs.b[j].numbits == 3))
packshift = 13;
else if((packshift == 6) && (bs.b[j].numbits == 3))
packshift = 10;
else if((packshift == 3) && (bs.b[j].numbits == 3))
packshift = 5;
else if((packshift == 0) && (bs.b[j].numbits == 3))
packshift = 2;
}
if(special3)
{
if(packshift == 12)
packshift = 13;
else if(packshift == 9)
packshift = 10;
else if(packshift == 6)
packshift = 5;
else if(packshift == 3)
packshift = 2;
else if(packshift == 0)
continue;
}
if(special4)
{
if(packshift == 10)
packshift = 11;
else if(packshift == 5)
packshift = 3;
else if(packshift == 0)
continue;
}
#if SPLITDEBUG
printf("PACKSHIFT:%i (on val %i) [filtered:%i] [shifted:%i]\n", packshift, packval, (bs.b[j].pattern >> bs.b[j].shiftbits), shifted);
#endif
revtarget = (packval >> packshift) & (bs.b[j].pattern >> bs.b[j].shiftbits);
#if SPLITDEBUG
printf(" -> reverse target @%i[pos:%i]:%u\n", j, k, revtarget);
#endif
target += revtarget << shifted;
shifted += bs.b[j].numbits;
#if SPLITDEBUG
printf(" => target: %i (shifted:%i)\n", target, shifted);
#endif
if(shifted >= outbits)
{
while(shifted >= 8)
{
// FIXME: special; only for w>=10?
if((special) && (shifted == bs.totalbits))
break;
#if SPLITDEBUG
printf("@%li: %i [extra]\n", bs.b[0].bufferctr, target & 0xFF);
#endif
if(bs.b[0].bufferctr % 1024 == 0)
bs.b[0].buffer = (char*)realloc(bs.b[0].buffer, (bs.b[0].bufferctr + 1024) * sizeof(char));
bs.b[0].buffer[bs.b[0].bufferctr] = target & 0xFF;
shifted -= 8;
bs.b[0].bufferctr++;
target = (target - (target & 0xFF)) >> 8;
}
}
}
}
}

return 0;
}

static int bitsplitwork(const char *inbuffer, ssize_t insize, bitsplit bs)
{
ssize_t i;
int j, k, l;
int target, shifted, inshifted;
int precounted;

fillbyte *b;
int totalbits;
int parts;
int redundant;

int outbits;
int stuffingthreshold;

b = bs.b;
totalbits = bs.totalbits;
parts = bs.parts;
redundant = bs.redundant;

outbits = 8;
inshifted = 0;
stuffingthreshold = totalbits * 8;

for(i = 0; i < insize; i++)
{
if(inshifted > 8)
{
inshifted -= 8;
i += 1;
}
#if SPLITDEBUG
printf("- source-pos:%li\n", i);
#endif
for(j = 0; j < parts; j++)
{
//target = inbuffer[i] & b[j].pattern;
target = (*(int*)(inbuffer + i)) & (b[j].pattern << inshifted);
target = target >> (b[j].shiftbits + inshifted);
#if SPLITDEBUG
printf(" -> target @%i[pos:%i]:%u\n", j, b[j].bitctr, target);
#endif

b[j].bits[b[j].bitctr] = target;
b[j].bitctr++;
if(b[j].bitctr == stuffingthreshold)
{
target = 0;
shifted = outbits - b[j].numbits;
precounted = 0;
for(k = 0; k < b[j].bitctr; k++)
{
#if SPLITDEBUG
printf("@%i: (%i->%i) >> %i ; << %i\n", j, b[j].numbits, b[j].bits[k], b[j].shiftbits, shifted);
#endif
target |= (b[j].bits[k] << shifted);
shifted -= b[j].numbits;
if(shifted < 0)
{
b[j].bytes[b[j].bytectr] = target & 0xFF;
b[j].bytectr++;
shifted = outbits - b[j].numbits;
precounted++;
#if SPLITDEBUG
printf("@%i: [bytectr++]: %i {%i}\n", j, target & 0xFF, target);
#endif
target = target >> outbits;
}
}
//b[j].bytectr += (int)((b[j].numbits * totalbits * 8 - 1) / 8) + 1 - precounted;
b[j].bytectr += (int)((totalbits - 1) / 8);
#if SPLITDEBUG
printf("@%i: stuffed %i 'bits'/fragments; bytectr now %i\n", j, totalbits, b[j].bytectr);
#endif
b[j].bitctr = 0;
if(b[j].bytectr >= 1024 - stuffingthreshold)
{
if((j == 0) && (redundant))
{
#if SPLITDEBUG
printf(">> redundancy\n");
#endif
b[parts].bytectr = b[j].bytectr;
for(l = 0; l < b[parts].bytectr; l++)
{
b[parts].bytes[l] = 0;
for(k = 0; k < parts; k++)
b[parts].bytes[l] ^= b[k].bytes[l];
}
if(b[parts].f)
fwrite(b[parts].bytes, 1, b[parts].bytectr, b[parts].f);
else
{
b[parts].buffer = (char*)realloc(b[parts].buffer, (b[parts].bufferctr + b[parts].bytectr) * sizeof(char));
memcpy(b[parts].buffer + b[parts].bufferctr, b[parts].bytes, b[parts].bytectr);
b[parts].bufferctr += b[parts].bytectr;
}
}
if(b[j].f)
fwrite(b[j].bytes, 1, b[j].bytectr, b[j].f);
else
{
b[j].buffer = (char*)realloc(b[j].buffer, (b[j].bufferctr + b[j].bytectr) * sizeof(char));
memcpy(b[j].buffer + b[j].bufferctr, b[j].bytes, b[j].bytectr);
b[j].bufferctr += b[j].bytectr;
}
b[j].bytectr = 0;
#if SPLITDEBUG
printf("@%i: reset bytectr\n", j);
#endif
}
}
}

i += (int)((totalbits - 1) / 8);
if((totalbits % 8) != 0)
{
inshifted += totalbits % 8;
if(inshifted % 8 == 0)
{
i += (inshifted - 8) / 8;
inshifted = 0;
}
else
i--;
}
}

for(j = 0; j < parts; j++)
{
if(b[j].bitctr > 0)
{
target = 0;
shifted = outbits - b[j].numbits;
precounted = 0;
for(k = 0; k < b[j].bitctr; k++)
{
#if SPLITDEBUG
printf("@%i: (%i=>%u) >> %i ; << %i\n", j, b[j].numbits, b[j].bits[k], b[j].shiftbits, shifted);
#endif
target |= (b[j].bits[k] << shifted);
shifted -= b[j].numbits;
if(shifted < 0)
{
b[j].bytes[b[j].bytectr] = target & 0xFF;
b[j].bytectr++;
shifted = outbits - b[j].numbits;
precounted++;
#if SPLITDEBUG
printf("@%i: [final-bytectr++]: %i {%i}\n", j, target & 0xFF, target);
#endif
target = target >> 8;
}
}
if(shifted != outbits - b[j].numbits)
{
#if SPLITDEBUG
printf("@%i: final-partialbyte: %i\n", j, target & 0xFF);
#endif
b[j].bytes[b[j].bytectr] = target & 0xFF;
b[j].bytectr++;
precounted++;
}
//b[j].bytectr += (int)((b[j].numbits * b[j].bitctr - 1) / totalbits) + 1 - precounted;
// FIXME: this may need a more general treatment
if(totalbits != 16)
b[j].bytectr += (int)((totalbits - 1) / 8);
#if SPLITDEBUG
printf("@%i: final-stuffed %i 'bits'/fragments; bytectr now %i\n", j, b[j].bitctr, b[j].bytectr);
#endif
b[j].bitctr = 0;
}
if(b[j].bytectr > 0)
{
if((j == 0) && (redundant))
{
#if SPLITDEBUG
printf(">> final-redundancy\n");
#endif
b[parts].bytectr = b[j].bytectr;
for(l = 0; l < b[parts].bytectr; l++)
{
b[parts].bytes[l] = 0;
for(k = 0; k < parts; k++)
b[parts].bytes[l] ^= b[k].bytes[l];
}
if(b[parts].f)
fwrite(b[parts].bytes, 1, b[parts].bytectr, b[parts].f);
else
{
b[parts].buffer = (char*)realloc(b[parts].buffer, (b[parts].bufferctr + b[parts].bytectr) * sizeof(char));
memcpy(b[parts].buffer + b[parts].bufferctr, b[parts].bytes, b[parts].bytectr);
b[parts].bufferctr += b[parts].bytectr;
}
}
if(b[j].f)
fwrite(b[j].bytes, 1, b[j].bytectr, b[j].f);
else
{
b[j].buffer = (char*)realloc(b[j].buffer, (b[j].bufferctr + b[j].bytectr) * sizeof(char));
memcpy(b[j].buffer + b[j].bufferctr, b[j].bytes, b[j].bytectr);
b[j].bufferctr += b[j].bytectr;
}
}
}

return 0;
}

int bitsplitbuffer(const char *inbuffer, ssize_t insize, char ***outbuffers, ssize_t **outsizes, int parts, int redundant, int bitwidth)
{
int ret;
int j;
bitsplit bs;

if((!inbuffer) || (parts <= 0)) return -1;
if(bitwidth < 1) return -1;

bs = bitsplitprepare(NULL, parts, redundant, bitwidth);
if(!bs.b) return -1;

*outbuffers = (char**)malloc((parts + redundant) * sizeof(char*));
*outsizes = (ssize_t*)malloc((parts + redundant) * sizeof(ssize_t));
for(j = 0; j < (parts + redundant); j++)
{
(*outbuffers)[j] = NULL;
(*outsizes)[j] = 0;
}

ret = bitsplitwork(inbuffer, insize, bs);

for(j = 0; j < (parts + redundant); j++)
{
(*outbuffers)[j] = bs.b[j].buffer;
(*outsizes)[j] = bs.b[j].bufferctr;
}

bitsplitfinish(bs);
return ret;
}

int bitjoinbuffer(const char **inbuffers, ssize_t *insizes, char **outbuffer, ssize_t *outsize, int parts, int bitwidth)
{
int ret;
bitsplit bs;

if((!inbuffers) || (parts <= 0)) return -1;

bs = bitsplitprepare(NULL, parts, 0, bitwidth);
if(!bs.b) return -1;

ret = bitjoinwork(inbuffers, insizes, bs);

*outbuffer = bs.b[0].buffer;
*outsize = bs.b[0].bufferctr;

bitsplitfinish(bs);
return ret;
}

int bitsplitfile(const char *filename, const char *directory, int parts, int redundant, int bitwidth)
{
FILE *f;
char buf[1024];
ssize_t size;
int ret;
bitsplit bs;

if((!filename) || (parts <= 0)) return -1;

f = fopen(filename, "r");
if(!f) return -1;

bs = bitsplitprepare(directory, parts, redundant, bitwidth);
if(!bs.b) return -1;

while(!feof(f))
{
size = fread(buf, 1, sizeof(buf), f);
#if SPLITDEBUG
printf("read %li bytes\n", size);
#endif

ret = bitsplitwork(buf, size, bs);
if(ret != 0)
{
fclose(f);
bitsplitfinish(bs);
return ret;
}
}

fclose(f);
bitsplitfinish(bs);
return 0;
}

int bitjoinfile(const char *filename, const char *directory, int parts, int bitwidth)
{
FILE *f, **dfs;
char **dbufs;
ssize_t *dsizes;
int ret;
//bitsplit bs;
int j;
char fname[1024];

if((!filename) || (parts <= 0)) return -1;

f = fopen(filename, "w");
if(!f) return -1;

dfs = (FILE**)malloc(parts * sizeof(FILE*));
dbufs = (char**)malloc(parts * sizeof(char**));
dsizes = (ssize_t*)malloc(parts * sizeof(ssize_t));

for(j = 0; j < parts; j++)
{
snprintf(fname, sizeof(fname), "%s/%i.stream", directory, j);
dfs[j] = fopen(fname, "r");
if(!dfs[j]) return -1;

dbufs[j] = (char*)malloc(1024 * sizeof(char));
}

//bs = bitsplitprepare(directory, parts, redundant, bitwidth);
//if(!bs.b) return -1;

while(!feof(dfs[0]))
{
for(j = 0; j < parts; j++)
{
dsizes[j] = fread(dbufs[j], 1, sizeof(dbufs[j]), dfs[j]);
#if SPLITDEBUG
printf("read %li bytes\n", dsizes[j]);
#endif
}

ret = -1;
//ret = bitsplitwork(buf, size, bs);
if(ret != 0)
{
for(j = 0; j < parts; j++)
fclose(dfs[j]);
fclose(f);
//bitsplitfinish(bs);
return ret;
}
}

for(j = 0; j < parts; j++)
fclose(dfs[j]);
fclose(f);
//bitsplitfinish(bs);
return 0;
}

please respond as soon as possible.

Finding Drivers For Canon CanoScan 4200F Scanner

I'm trying to get a Canon CanoScan 4200F scanner to work in both Kubuntu 12.04 and Calculate 13.6, and I've had no luck, using either SimpleScan or Xsane. The Canon website is no help; it simply says that Canon supplies no drivers for that device for any Linux distro. Does anybody know where to get drivers that work w\ Canon devices?

The following is the output from lsusb:
lsusb | grep -i 'canon'
Bus 007 Device 002: ID 04a9:221b Canon, Inc. CanoScan 4200F

Thanx in advance.