summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-06-16 02:30:41 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-06-16 02:30:41 +0200
commit8dff8642c43a473713d48533974d9c7883bbc5c1 (patch)
treeea8513c76d38f2612a1202d30abf0f2e768f204c /src
parent1c73d171b2814bf2809aa48c2d4b683a064a4f7e (diff)
refactor: Replace hwdata by mtdev
This patch makes the switch, from using hwdata and the associated type A parser, to using mtdev and the associated type B parser. A command-line gesture test program is included. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src')
-rw-r--r--src/gestures.c26
-rw-r--r--src/hwstate.c156
-rw-r--r--src/memory.c33
-rw-r--r--src/mtouch.c20
-rw-r--r--src/mtstate.c45
-rw-r--r--src/test.c45
6 files changed, 182 insertions, 143 deletions
diff --git a/src/gestures.c b/src/gestures.c
index 0cc2e0b..663f1a4 100644
--- a/src/gestures.c
+++ b/src/gestures.c
@@ -81,8 +81,8 @@ static void extract_movement(struct Gestures *gs, struct MTouch* mt)
81 return; 81 return;
82 82
83 foreach_bit(i, mt->mem.moving) { 83 foreach_bit(i, mt->mem.moving) {
84 xp[i] = mt->state.finger[i].hw.position_x - xpos; 84 xp[i] = mt->state.finger[i].position_x - xpos;
85 yp[i] = mt->state.finger[i].hw.position_y - ypos; 85 yp[i] = mt->state.finger[i].position_y - ypos;
86 xm[i] = mt->mem.dx[i]; 86 xm[i] = mt->mem.dx[i];
87 ym[i] = mt->mem.dy[i]; 87 ym[i] = mt->mem.dy[i];
88 mt->mem.dx[i] = 0; 88 mt->mem.dx[i] = 0;
@@ -178,3 +178,25 @@ void extract_gestures(struct Gestures *gs, struct MTouch* mt)
178 mt->prev_state = mt->state; 178 mt->prev_state = mt->state;
179} 179}
180 180
181
182void output_gesture(const struct Gestures *gs)
183{
184 int i;
185 foreach_bit(i, gs->btmask)
186 xf86Msg(X_INFO, "button bit: %d %d\n",
187 i, GETBIT(gs->btdata, i));
188 if (GETBIT(gs->type, GS_MOVE))
189 xf86Msg(X_INFO, "motion: %d %d\n", gs->dx, gs->dy);
190 if (GETBIT(gs->type, GS_VSCROLL))
191 xf86Msg(X_INFO, "vscroll: %d\n", gs->dy);
192 if (GETBIT(gs->type, GS_HSCROLL))
193 xf86Msg(X_INFO, "hscroll: %d\n", gs->dx);
194 if (GETBIT(gs->type, GS_VSWIPE))
195 xf86Msg(X_INFO, "vswipe: %d\n", gs->dy);
196 if (GETBIT(gs->type, GS_HSWIPE))
197 xf86Msg(X_INFO, "hswipe: %d\n", gs->dx);
198 if (GETBIT(gs->type, GS_SCALE))
199 xf86Msg(X_INFO, "scale: %d\n", gs->scale);
200 if (GETBIT(gs->type, GS_ROTATE))
201 xf86Msg(X_INFO, "rotate: %d\n", gs->rot);
202}
diff --git a/src/hwstate.c b/src/hwstate.c
index 032351c..f4f2972 100644
--- a/src/hwstate.c
+++ b/src/hwstate.c
@@ -21,91 +21,101 @@
21 21
22#include "hwstate.h" 22#include "hwstate.h"
23 23
24#define NOTOUCH(hw, c) ((hw)->touch_major == 0 && (c)->has_abs[BIT_TOUCH_MAJOR]) 24void init_hwstate(struct HWState *s, const struct Capabilities *caps)
25
26void init_hwstate(struct HWState *s)
27{ 25{
26 int i;
28 memset(s, 0, sizeof(struct HWState)); 27 memset(s, 0, sizeof(struct HWState));
28 for (i = 0; i < DIM_FINGER; i++)
29 s->data[i].tracking_id = caps->nullid;
29} 30}
30 31
31/* Dmitry Torokhov's code from kernel/driver/input/input.c */ 32static void finish_packet(struct HWState *s, const struct Capabilities *caps,
32static int defuzz(int value, int old_val, int fuzz) 33 const struct input_event *syn)
33{ 34{
34 if (fuzz) { 35 static const mstime_t ms = 1000;
35 if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2) 36 int i;
36 return old_val; 37 foreach_bit(i, s->used) {
37 38 if (!caps->has_abs[BIT_TOUCH_MINOR])
38 if (value > old_val - fuzz && value < old_val + fuzz) 39 s->data[i].touch_minor = s->data[i].touch_major;
39 return (old_val * 3 + value) / 4; 40 if (!caps->has_abs[BIT_WIDTH_MINOR])
40 41 s->data[i].width_minor = s->data[i].width_major;
41 if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
42 return (old_val + value) / 2;
43 } 42 }
44 43 s->evtime = syn->time.tv_usec / ms + syn->time.tv_sec * ms;
45 return value;
46} 44}
47 45
48static void set_finger(struct FingerState *fs, 46static int read_event(struct HWState *s, const struct Capabilities *caps,
49 const struct FingerData *hw, int id, 47 const struct input_event *ev)
50 const struct Capabilities *caps)
51{ 48{
52 int x = defuzz(hw->position_x, fs->hw.position_x, caps->abs[BIT_POSITION_X].fuzz); 49 switch (ev->type) {
53 int y = defuzz(hw->position_y, fs->hw.position_y, caps->abs[BIT_POSITION_Y].fuzz); 50 case EV_SYN:
54 int tj = defuzz(hw->touch_major, fs->hw.touch_major, caps->abs[BIT_TOUCH_MAJOR].fuzz); 51 switch (ev->code) {
55 int tn = defuzz(hw->touch_minor, fs->hw.touch_minor, caps->abs[BIT_TOUCH_MAJOR].fuzz); 52 case SYN_REPORT:
56 int wj = defuzz(hw->width_major, fs->hw.width_major, caps->abs[BIT_TOUCH_MAJOR].fuzz); 53 finish_packet(s, caps, ev);
57 int wn = defuzz(hw->width_minor, fs->hw.width_minor, caps->abs[BIT_TOUCH_MAJOR].fuzz); 54 return 1;
58 fs->id = id; 55 }
59 fs->hw = *hw; 56 break;
60 fs->hw.position_x = x; 57 case EV_KEY:
61 fs->hw.position_y = y; 58 switch (ev->code) {
62 if (hw->touch_major) { 59 case BTN_LEFT:
63 fs->hw.touch_major = tj; 60 MODBIT(s->button, MT_BUTTON_LEFT, ev->value);
64 fs->hw.touch_minor = tn; 61 break;
62 case BTN_MIDDLE:
63 MODBIT(s->button, MT_BUTTON_MIDDLE, ev->value);
64 break;
65 case BTN_RIGHT:
66 MODBIT(s->button, MT_BUTTON_RIGHT, ev->value);
67 break;
68 }
69 break;
70 case EV_ABS:
71 switch (ev->code) {
72 case ABS_MT_SLOT:
73 if (ev->value >= 0 && ev->value < DIM_FINGER)
74 s->slot = ev->value;
75 break;
76 case ABS_MT_TOUCH_MAJOR:
77 s->data[s->slot].touch_major = ev->value;
78 break;
79 case ABS_MT_TOUCH_MINOR:
80 s->data[s->slot].touch_minor = ev->value;
81 break;
82 case ABS_MT_WIDTH_MAJOR:
83 s->data[s->slot].width_major = ev->value;
84 break;
85 case ABS_MT_WIDTH_MINOR:
86 s->data[s->slot].width_minor = ev->value;
87 break;
88 case ABS_MT_ORIENTATION:
89 s->data[s->slot].orientation = ev->value;
90 break;
91 case ABS_MT_PRESSURE:
92 s->data[s->slot].pressure = ev->value;
93 break;
94 case ABS_MT_POSITION_X:
95 s->data[s->slot].position_x = ev->value;
96 break;
97 case ABS_MT_POSITION_Y:
98 s->data[s->slot].position_y = ev->value;
99 break;
100 case ABS_MT_TRACKING_ID:
101 s->data[s->slot].tracking_id = ev->value;
102 MODBIT(s->used, s->slot,
103 ev->value != caps->nullid);
104 break;
105 }
106 break;
65 } 107 }
66 fs->hw.width_major = wj; 108 return 0;
67 fs->hw.width_minor = wn;
68 if (!caps->has_abs[BIT_TOUCH_MINOR])
69 fs->hw.touch_minor = hw->touch_major;
70 if (!caps->has_abs[BIT_WIDTH_MINOR])
71 fs->hw.width_minor = hw->width_major;
72} 109}
73 110
74void modify_hwstate(struct HWState *s, 111int modify_hwstate(struct HWState *s, struct MTDev *dev,
75 const struct HWData *hw, 112 const struct Capabilities *caps)
76 const struct Capabilities *caps)
77{ 113{
78 int A[DIM2_FINGER], *row; 114 struct input_event ev;
79 int sid[DIM_FINGER], hw2s[DIM_FINGER]; 115 while (!mtdev_empty(dev)) {
80 int id, i, j; 116 mtdev_pop(dev, &ev);
81 117 if (read_event(s, caps, &ev))
82 /* setup distance matrix for finger id matching */ 118 return 1;
83 for (j = 0; j < s->nfinger; j++) {
84 sid[j] = s->finger[j].id;
85 if (NOTOUCH(&s->finger[j].hw, caps))
86 sid[j] = 0;
87 row = A + hw->nfinger * j;
88 for (i = 0; i < hw->nfinger; i++)
89 row[i] = finger_dist2(&hw->finger[i], &s->finger[j].hw);
90 } 119 }
91 120 return 0;
92 match_fingers(hw2s, A, hw->nfinger, s->nfinger);
93
94 /* update matched fingers and create new ones */
95 for (i = 0; i < hw->nfinger; i++) {
96 j = hw2s[i];
97 id = j >= 0 ? sid[j] : 0;
98 if (!NOTOUCH(&hw->finger[i], caps))
99 while (!id)
100 id = ++s->lastid;
101 set_finger(&s->finger[i], &hw->finger[i], id, caps);
102 }
103
104 /* clear remaining finger ids */
105 for (i = hw->nfinger; i < s->nfinger; i++)
106 s->finger[i].id = 0;
107
108 s->button = hw->button;
109 s->nfinger = hw->nfinger;
110 s->evtime = hw->evtime;
111} 121}
diff --git a/src/memory.c b/src/memory.c
index 4cfb7da..748aa07 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -32,13 +32,15 @@ static const int FINGER_ATTACK_MS = 40;
32static const int FINGER_DECAY_MS = 120; 32static const int FINGER_DECAY_MS = 120;
33static const int FINGER_CORNER_MS = 150; 33static const int FINGER_CORNER_MS = 150;
34 34
35static inline int dxval(const struct MTFinger *a, const struct MTFinger *b) 35static inline int dxval(const struct FingerState *a,
36 const struct FingerState *b)
36{ 37{
37 return a->hw.position_x - b->hw.position_x; 38 return a->position_x - b->position_x;
38} 39}
39static inline int dyval(const struct MTFinger *a, const struct MTFinger *b) 40static inline int dyval(const struct FingerState *a,
41 const struct FingerState *b)
40{ 42{
41 return a->hw.position_y - b->hw.position_y; 43 return a->position_y - b->position_y;
42} 44}
43 45
44void init_memory(struct Memory *mem) 46void init_memory(struct Memory *mem)
@@ -60,20 +62,18 @@ static void update_configuration(struct Memory *m,
60 const struct MTState *prev_state, 62 const struct MTState *prev_state,
61 const struct MTState *state) 63 const struct MTState *state)
62{ 64{
63 const struct MTFinger *f = state->finger; 65 const struct FingerState *f = state->finger;
64 bitmask_t fingers = BITONES(state->nfinger); 66 bitmask_t fingers = BITONES(state->nfinger);
65 int i; 67 int i;
66 m->added = 0; 68 m->added = 0;
67 foreach_bit(i, fingers) 69 foreach_bit(i, fingers)
68 if (!find_finger(prev_state, f[i].id)) 70 if (!find_finger(prev_state, f[i].tracking_id))
69 SETBIT(m->added, i); 71 SETBIT(m->added, i);
70 m->same = m->fingers == fingers && m->added == 0; 72 m->same = m->fingers == fingers && m->added == 0;
71 m->fingers = fingers; 73 m->fingers = fingers;
72 if (!m->same) 74 if (!m->same)
73 m->thumb = 0; 75 m->thumb = 0;
74 foreach_bit(i, fingers) 76 m->thumb |= state->thumb;
75 if (f[i].thumb)
76 SETBIT(m->thumb, i);
77} 77}
78 78
79/** 79/**
@@ -90,8 +90,9 @@ static void update_pointers(struct Memory *m,
90 const struct MTState *state, 90 const struct MTState *state,
91 const struct Capabilities *caps) 91 const struct Capabilities *caps)
92{ 92{
93 const struct MTFinger *f = state->finger; 93 const struct FingerState *f = state->finger;
94 int yclick = caps->abs[BIT_POSITION_Y].maximum - CLICK_AREA(caps); 94 int yclick = caps->abs[BIT_POSITION_Y].maximum - CLICK_AREA(caps);
95
95 int i; 96 int i;
96 97
97 if (state->nfinger < 2) { 98 if (state->nfinger < 2) {
@@ -102,7 +103,7 @@ static void update_pointers(struct Memory *m,
102 103
103 if (m->same) { 104 if (m->same) {
104 foreach_bit(i, m->fingers & ~m->pointing) { 105 foreach_bit(i, m->fingers & ~m->pointing) {
105 if (f[i].hw.position_y <= m->ybar) { 106 if (f[i].position_y <= m->ybar) {
106 m->pointing = m->fingers; 107 m->pointing = m->fingers;
107 return; 108 return;
108 } 109 }
@@ -113,10 +114,10 @@ static void update_pointers(struct Memory *m,
113 m->pointing = 0; 114 m->pointing = 0;
114 m->ybar = yclick; 115 m->ybar = yclick;
115 foreach_bit(i, m->fingers) { 116 foreach_bit(i, m->fingers) {
116 if (f[i].hw.position_y > yclick) 117 if (f[i].position_y > yclick)
117 continue; 118 continue;
118 if (!m->pointing || f[i].hw.position_y > m->ybar) 119 if (!m->pointing || f[i].position_y > m->ybar)
119 m->ybar = f[i].hw.position_y; 120 m->ybar = f[i].position_y;
120 SETBIT(m->pointing, i); 121 SETBIT(m->pointing, i);
121 } 122 }
122 123
@@ -140,7 +141,7 @@ static void update_movement(struct Memory *m,
140 const struct MTState *state, 141 const struct MTState *state,
141 const struct Capabilities *caps) 142 const struct Capabilities *caps)
142{ 143{
143 const struct MTFinger *prev, *f = state->finger; 144 const struct FingerState *prev, *f = state->finger;
144 int i, xcut, ycut, xmax = 0, ymax = 0; 145 int i, xcut, ycut, xmax = 0, ymax = 0;
145 146
146 m->moving = 0; 147 m->moving = 0;
@@ -167,7 +168,7 @@ static void update_movement(struct Memory *m,
167 168
168 foreach_bit(i, m->pointing) { 169 foreach_bit(i, m->pointing) {
169 int dx, dy; 170 int dx, dy;
170 prev = find_finger(prev_state, f[i].id); 171 prev = find_finger(prev_state, f[i].tracking_id);
171 dx = dxval(&f[i], prev); 172 dx = dxval(&f[i], prev);
172 dy = dyval(&f[i], prev); 173 dy = dyval(&f[i], prev);
173 m->dx[i] += dx; 174 m->dx[i] += dx;
diff --git a/src/mtouch.c b/src/mtouch.c
index ad077b7..959783a 100644
--- a/src/mtouch.c
+++ b/src/mtouch.c
@@ -33,9 +33,9 @@ int configure_mtouch(struct MTouch *mt, int fd)
33int open_mtouch(struct MTouch *mt, int fd) 33int open_mtouch(struct MTouch *mt, int fd)
34{ 34{
35 int rc; 35 int rc;
36 mtdev_init(&mt->dev, &mt->caps);
36 init_iobuf(&mt->buf); 37 init_iobuf(&mt->buf);
37 init_hwdata(&mt->hw); 38 init_hwstate(&mt->hs, &mt->caps);
38 init_hwstate(&mt->hs);
39 init_mtstate(&mt->prev_state); 39 init_mtstate(&mt->prev_state);
40 init_mtstate(&mt->state); 40 init_mtstate(&mt->state);
41 init_memory(&mt->mem); 41 init_memory(&mt->mem);
@@ -50,18 +50,11 @@ int close_mtouch(struct MTouch *mt, int fd)
50 return rc; 50 return rc;
51} 51}
52 52
53int read_synchronized_event(struct MTouch *mt, int fd) 53int parse_event(struct MTouch *mt, const struct input_event *ev)
54{ 54{
55 const struct input_event *ev; 55 mtdev_push(&mt->dev, &mt->caps, ev);
56 while (ev = get_iobuf_event(&mt->buf, fd)) 56 if (!modify_hwstate(&mt->hs, &mt->dev, &mt->caps))
57 if (read_hwdata(&mt->hw, ev)) 57 return 0;
58 return 1;
59 return 0;
60}
61
62void parse_event(struct MTouch *mt)
63{
64 modify_hwstate(&mt->hs, &mt->hw, &mt->caps);
65 extract_mtstate(&mt->state, &mt->hs, &mt->caps); 58 extract_mtstate(&mt->state, &mt->hs, &mt->caps);
66#if 0 59#if 0
67 output_mtstate(&mt->state); 60 output_mtstate(&mt->state);
@@ -70,4 +63,5 @@ void parse_event(struct MTouch *mt)
70#if 0 63#if 0
71 output_memory(&mt->mem); 64 output_memory(&mt->mem);
72#endif 65#endif
66 return 1;
73} 67}
diff --git a/src/mtstate.c b/src/mtstate.c
index 2403765..7a8ef19 100644
--- a/src/mtstate.c
+++ b/src/mtstate.c
@@ -34,7 +34,7 @@ void init_mtstate(struct MTState *s)
34 memset(s, 0, sizeof(struct MTState)); 34 memset(s, 0, sizeof(struct MTState));
35} 35}
36 36
37static int touching_finger(const struct FingerData *hw, 37static int touching_finger(const struct FingerState *hw,
38 const struct Capabilities *caps) 38 const struct Capabilities *caps)
39{ 39{
40 if (caps->has_abs[BIT_TOUCH_MAJOR] && caps->has_abs[BIT_WIDTH_MAJOR]) 40 if (caps->has_abs[BIT_TOUCH_MAJOR] && caps->has_abs[BIT_WIDTH_MAJOR])
@@ -52,8 +52,8 @@ static int touching_finger(const struct FingerData *hw,
52 * by all three values touch_major, width_minor, and trackpad size. 52 * by all three values touch_major, width_minor, and trackpad size.
53 * 53 *
54 */ 54 */
55static int thumb_finger(const struct FingerData *hw, 55static int is_thumb(const struct FingerState *hw,
56 const struct Capabilities *caps) 56 const struct Capabilities *caps)
57{ 57{
58 if (!caps->has_abs[BIT_TOUCH_MAJOR] || 58 if (!caps->has_abs[BIT_TOUCH_MAJOR] ||
59 !caps->has_abs[BIT_TOUCH_MINOR] || 59 !caps->has_abs[BIT_TOUCH_MINOR] ||
@@ -66,26 +66,17 @@ static int thumb_finger(const struct FingerData *hw,
66 hw->width_major > THUMB_WIDTH_SIZE(hw, caps); 66 hw->width_major > THUMB_WIDTH_SIZE(hw, caps);
67} 67}
68 68
69static int set_finger(struct MTFinger *f,
70 const struct FingerState *fs,
71 const struct Capabilities *caps)
72{
73 f->hw = fs->hw;
74 f->id = fs->id;
75 f->thumb = thumb_finger(&fs->hw, caps);
76}
77
78void extract_mtstate(struct MTState *s, 69void extract_mtstate(struct MTState *s,
79 const struct HWState *hs, 70 const struct HWState *hs,
80 const struct Capabilities *caps) 71 const struct Capabilities *caps)
81{ 72{
82 int i; 73 int i;
83
84 s->nfinger = 0; 74 s->nfinger = 0;
85 for (i = 0; i < hs->nfinger; i++) { 75 foreach_bit(i, hs->used) {
86 if (!touching_finger(&hs->finger[i].hw, caps)) 76 if (!touching_finger(&hs->data[i], caps))
87 continue; 77 continue;
88 set_finger(&s->finger[s->nfinger], &hs->finger[i], caps); 78 s->finger[s->nfinger] = hs->data[i];
79 MODBIT(s->thumb, s->nfinger, is_thumb(&hs->data[i], caps));
89 s->nfinger++; 80 s->nfinger++;
90 } 81 }
91 82
@@ -93,12 +84,12 @@ void extract_mtstate(struct MTState *s,
93 s->evtime = hs->evtime; 84 s->evtime = hs->evtime;
94} 85}
95 86
96const struct MTFinger *find_finger(const struct MTState *s, int id) 87const struct FingerState *find_finger(const struct MTState *s, int id)
97{ 88{
98 int i; 89 int i;
99 90
100 for (i = 0; i < s->nfinger; i++) 91 for (i = 0; i < s->nfinger; i++)
101 if (s->finger[i].id == id) 92 if (s->finger[i].tracking_id == id)
102 return s->finger + i; 93 return s->finger + i;
103 94
104 return NULL; 95 return NULL;
@@ -119,14 +110,14 @@ void output_mtstate(const struct MTState *s)
119 xf86Msg(X_INFO, 110 xf86Msg(X_INFO,
120 " %+02d %+05d:%+05d +%05d:%+05d " 111 " %+02d %+05d:%+05d +%05d:%+05d "
121 "%+06d %+06d %+05d:%+05d\n", 112 "%+06d %+06d %+05d:%+05d\n",
122 s->finger[i].id, 113 s->finger[i].tracking_id,
123 s->finger[i].hw.touch_major, 114 s->finger[i].touch_major,
124 s->finger[i].hw.touch_minor, 115 s->finger[i].touch_minor,
125 s->finger[i].hw.width_major, 116 s->finger[i].width_major,
126 s->finger[i].hw.width_minor, 117 s->finger[i].width_minor,
127 s->finger[i].hw.orientation, 118 s->finger[i].orientation,
128 s->finger[i].hw.pressure, 119 s->finger[i].pressure,
129 s->finger[i].hw.position_x, 120 s->finger[i].position_x,
130 s->finger[i].hw.position_y); 121 s->finger[i].position_y);
131 } 122 }
132} 123}
diff --git a/src/test.c b/src/test.c
index 7d983a0..0088cdd 100644
--- a/src/test.c
+++ b/src/test.c
@@ -19,24 +19,45 @@
19 * 19 *
20 **************************************************************************/ 20 **************************************************************************/
21 21
22#include <common.h> 22#include <gestures.h>
23#include <fcntl.h>
23#include <xbypass.h> 24#include <xbypass.h>
24#include <stdio.h>
25#include <time.h>
26 25
27static void print_bitfield(unsigned m) 26static void loop_device(int fd)
28{ 27{
29 int i; 28 struct Gestures gs;
30 29 struct MTouch mt;
31 printf("%d\n", m); 30 const struct input_event *ev;
32 foreach_bit(i, m) 31 struct input_event event;
33 printf("%d %d\n", i, 1 << i); 32 if (configure_mtouch(&mt, fd)) {
33 fprintf(stderr, "error: could not configure device\n");
34 return;
35 }
36 if (open_mtouch(&mt, fd)) {
37 fprintf(stderr, "error: could not open device\n");
38 return;
39 }
40 while (ev = get_iobuf_event(&mt.buf, fd)) {
41 if (parse_event(&mt, ev)) {
42 extract_gestures(&gs, &mt);
43 output_gesture(&gs);
44 }
45 }
46 close_mtouch(&mt, fd);
34} 47}
35 48
36int main(int argc, char *argv[]) 49int main(int argc, char *argv[])
37{ 50{
38 print_bitfield(5); 51 if (argc < 2) {
39 print_bitfield(126); 52 fprintf(stderr, "Usage: test <mtdev>\n");
40 print_bitfield(0); 53 return -1;
54 }
55 int fd = open(argv[1], O_RDONLY);
56 if (fd < 0) {
57 fprintf(stderr, "error: could not open file\n");
58 return -1;
59 }
60 loop_device(fd);
61 close(fd);
41 return 0; 62 return 0;
42} 63}