10948c0ffSMichael Lotz /*
20948c0ffSMichael Lotz * Copyright 2012, Haiku, Inc. All rights reserved.
30948c0ffSMichael Lotz * Distributed under the terms of the MIT License.
40948c0ffSMichael Lotz *
50948c0ffSMichael Lotz * Authors:
60948c0ffSMichael Lotz * Michael Lotz <mmlr@mlotz.ch>
70948c0ffSMichael Lotz */
80948c0ffSMichael Lotz
90948c0ffSMichael Lotz
100948c0ffSMichael Lotz #include <debug.h>
11a86c7d0aSMichael Lotz #include <stdio.h>
120948c0ffSMichael Lotz #include <stdlib.h>
130948c0ffSMichael Lotz #include <string.h>
140948c0ffSMichael Lotz
150948c0ffSMichael Lotz extern "C" {
160948c0ffSMichael Lotz #include "qrencode.h"
170948c0ffSMichael Lotz #include "qrspec.h"
180948c0ffSMichael Lotz }
190948c0ffSMichael Lotz
200948c0ffSMichael Lotz
21e0ef5b2aSMichael Lotz extern "C" {
22e0ef5b2aSMichael Lotz extern void abort_debugger_command();
23e0ef5b2aSMichael Lotz }
24e0ef5b2aSMichael Lotz
25e0ef5b2aSMichael Lotz
262a80abaaSMichael Lotz static const char* kWebPostBaseURL = "http://mlotz.ch/q";
27a86c7d0aSMichael Lotz
280948c0ffSMichael Lotz static char sStringBuffer[16 * 1024];
290948c0ffSMichael Lotz static char sEncodeBuffer[3 * 1024];
300948c0ffSMichael Lotz static int sBufferPosition = 0;
310948c0ffSMichael Lotz static int sQRCodeVersion = 19;
320948c0ffSMichael Lotz static QRecLevel sQRCodeLevel = QR_ECLEVEL_L;
33a86c7d0aSMichael Lotz static char sWebPostId[64];
34a86c7d0aSMichael Lotz static int sWebPostCounter = 0;
350948c0ffSMichael Lotz
360948c0ffSMichael Lotz
370948c0ffSMichael Lotz static bool
qrcode_bit(QRcode * qrCode,int x,int y)380948c0ffSMichael Lotz qrcode_bit(QRcode* qrCode, int x, int y)
390948c0ffSMichael Lotz {
400948c0ffSMichael Lotz if (x >= qrCode->width || y >= qrCode->width)
410948c0ffSMichael Lotz return false;
420948c0ffSMichael Lotz
430948c0ffSMichael Lotz return (qrCode->data[y * qrCode->width + x] & 0x01) == 1;
440948c0ffSMichael Lotz }
450948c0ffSMichael Lotz
460948c0ffSMichael Lotz
470948c0ffSMichael Lotz static void
move_to_and_clear_line(int line)480948c0ffSMichael Lotz move_to_and_clear_line(int line)
490948c0ffSMichael Lotz {
500948c0ffSMichael Lotz kprintf(" \x1b[%dd\x1b[G\x1b[K", line + 1);
510948c0ffSMichael Lotz }
520948c0ffSMichael Lotz
530948c0ffSMichael Lotz
5439a26a0aSMichael Lotz static bool
print_qrcode(QRcode * qrCode,bool waitForKey)550948c0ffSMichael Lotz print_qrcode(QRcode* qrCode, bool waitForKey)
560948c0ffSMichael Lotz {
570948c0ffSMichael Lotz move_to_and_clear_line(0);
580948c0ffSMichael Lotz for (int y = 0; y < qrCode->width; y += 2) {
590948c0ffSMichael Lotz move_to_and_clear_line(y / 2 + 1);
600948c0ffSMichael Lotz kputs(" ");
610948c0ffSMichael Lotz
620948c0ffSMichael Lotz for (int x = 0; x < qrCode->width; x++) {
630948c0ffSMichael Lotz bool upper = qrcode_bit(qrCode, x, y);
640948c0ffSMichael Lotz bool lower = qrcode_bit(qrCode, x, y + 1);
650948c0ffSMichael Lotz if (upper == lower)
660948c0ffSMichael Lotz kputs(upper ? "\x11" : " ");
670948c0ffSMichael Lotz else
680948c0ffSMichael Lotz kputs(upper ? "\x12" : "\x13");
690948c0ffSMichael Lotz }
700948c0ffSMichael Lotz }
710948c0ffSMichael Lotz
720948c0ffSMichael Lotz move_to_and_clear_line(qrCode->width / 2 + 2);
730948c0ffSMichael Lotz move_to_and_clear_line(qrCode->width / 2 + 3);
740948c0ffSMichael Lotz
750948c0ffSMichael Lotz if (waitForKey) {
76e0ef5b2aSMichael Lotz kputs("press q to abort or any other key to continue...\x1b[1B\x1b[G");
77e0ef5b2aSMichael Lotz if (kgetc() == 'q')
7839a26a0aSMichael Lotz return false;
790948c0ffSMichael Lotz }
8039a26a0aSMichael Lotz
8139a26a0aSMichael Lotz return true;
820948c0ffSMichael Lotz }
830948c0ffSMichael Lotz
840948c0ffSMichael Lotz
850948c0ffSMichael Lotz static int
encode_url(const char * query,const char * data,int encodeLength,int inputLength)86a86c7d0aSMichael Lotz encode_url(const char* query, const char* data, int encodeLength,
87a86c7d0aSMichael Lotz int inputLength)
88a86c7d0aSMichael Lotz {
89a86c7d0aSMichael Lotz sEncodeBuffer[0] = 0;
90a86c7d0aSMichael Lotz strlcat(sEncodeBuffer, kWebPostBaseURL, encodeLength + 1);
912a80abaaSMichael Lotz strlcat(sEncodeBuffer, "?i=", encodeLength + 1);
92a86c7d0aSMichael Lotz strlcat(sEncodeBuffer, sWebPostId, encodeLength + 1);
93a86c7d0aSMichael Lotz strlcat(sEncodeBuffer, "&", encodeLength + 1);
94a86c7d0aSMichael Lotz strlcat(sEncodeBuffer, query, encodeLength + 1);
95a86c7d0aSMichael Lotz int position = strlcat(sEncodeBuffer, "=", encodeLength + 1);
96a86c7d0aSMichael Lotz if (position > encodeLength)
97a86c7d0aSMichael Lotz return -1;
98a86c7d0aSMichael Lotz
99a86c7d0aSMichael Lotz int copyCount = 0;
100a86c7d0aSMichael Lotz while (inputLength > 0 && position < encodeLength) {
101a86c7d0aSMichael Lotz char character = data[copyCount];
102a86c7d0aSMichael Lotz if ((character >= 'a' && character <= 'z')
103a86c7d0aSMichael Lotz || (character >= 'A' && character <= 'Z')
104a86c7d0aSMichael Lotz || (character >= '0' && character <= '9')
105a86c7d0aSMichael Lotz || character == '.' || character == '-' || character == '_'
106*5dc5dbbbSMichael Lotz || character == '~'
107*5dc5dbbbSMichael Lotz // These aren't strictly valid, but seem to work.
108*5dc5dbbbSMichael Lotz || character == '/' || character == '(' || character == ')'
109*5dc5dbbbSMichael Lotz || character == '=' || character == '^' || character == '?'
110*5dc5dbbbSMichael Lotz || character == '|' || character == '*' || character == '@'
111*5dc5dbbbSMichael Lotz || character == ';' || character == ':' || character == ','
112*5dc5dbbbSMichael Lotz || character == '{' || character == '}' || character == '['
113*5dc5dbbbSMichael Lotz || character == ']' || character == '<' || character == '>'
114*5dc5dbbbSMichael Lotz || character == '!' || character == '\\') {
115a86c7d0aSMichael Lotz sEncodeBuffer[position++] = character;
116a86c7d0aSMichael Lotz sEncodeBuffer[position] = 0;
117*5dc5dbbbSMichael Lotz } else if (character == ' ') {
118*5dc5dbbbSMichael Lotz // Encode spaces as '+' as that's shorter than %20.
119*5dc5dbbbSMichael Lotz sEncodeBuffer[position++] = '+';
120*5dc5dbbbSMichael Lotz sEncodeBuffer[position] = 0;
121a86c7d0aSMichael Lotz } else {
122a86c7d0aSMichael Lotz // Encode to a %xx escape.
123a86c7d0aSMichael Lotz if (encodeLength - position < 3) {
124a86c7d0aSMichael Lotz // Doesn't fit anymore, we're done.
125a86c7d0aSMichael Lotz break;
126a86c7d0aSMichael Lotz }
127a86c7d0aSMichael Lotz
128a86c7d0aSMichael Lotz char escaped[4];
129a86c7d0aSMichael Lotz sprintf(escaped, "%%%.2x", character);
130a86c7d0aSMichael Lotz position = strlcat(sEncodeBuffer, escaped, encodeLength + 1);
131a86c7d0aSMichael Lotz }
132a86c7d0aSMichael Lotz
133a86c7d0aSMichael Lotz inputLength--;
134a86c7d0aSMichael Lotz copyCount++;
135a86c7d0aSMichael Lotz }
136a86c7d0aSMichael Lotz
137a86c7d0aSMichael Lotz return copyCount;
138a86c7d0aSMichael Lotz }
139a86c7d0aSMichael Lotz
140a86c7d0aSMichael Lotz
141a86c7d0aSMichael Lotz static int
qrencode(int argc,char * argv[])1420948c0ffSMichael Lotz qrencode(int argc, char* argv[])
1430948c0ffSMichael Lotz {
1440948c0ffSMichael Lotz if (argc > 1 && strcmp(argv[1], "--help") == 0) {
1450948c0ffSMichael Lotz kprintf("%s [<string>]\n", argv[0]);
1460948c0ffSMichael Lotz kprintf("If an argument is given, encodes that string as a QR code.\n"
1470948c0ffSMichael Lotz "Otherwise the current QR buffer is encoded as QR codes.\n"
1480948c0ffSMichael Lotz "When encoding from the QR buffer, the buffer is left intact.\n"
1490948c0ffSMichael Lotz "use qrclear to clear the QR buffer or qrflush to encode/clear.\n");
1500948c0ffSMichael Lotz return 1;
1510948c0ffSMichael Lotz }
1520948c0ffSMichael Lotz
1530948c0ffSMichael Lotz const char* source = NULL;
1540948c0ffSMichael Lotz if (argc < 2) {
1550948c0ffSMichael Lotz sStringBuffer[sBufferPosition] = 0;
1560948c0ffSMichael Lotz source = sStringBuffer;
1570948c0ffSMichael Lotz } else
1580948c0ffSMichael Lotz source = argv[1];
1590948c0ffSMichael Lotz
1600948c0ffSMichael Lotz int inputLength = strlen(source);
1610948c0ffSMichael Lotz int encodeLength = QRspec_getDataLength(sQRCodeVersion, sQRCodeLevel) - 3;
1620948c0ffSMichael Lotz while (inputLength > 0) {
163a86c7d0aSMichael Lotz int copyCount = 0;
164a86c7d0aSMichael Lotz if (sWebPostId[0] != 0) {
1652a80abaaSMichael Lotz copyCount = encode_url(sWebPostCounter++ == 0 ? "clear" : "d",
166a86c7d0aSMichael Lotz source, encodeLength, inputLength);
167a86c7d0aSMichael Lotz if (copyCount < 0) {
168a86c7d0aSMichael Lotz kprintf("Failed to URL encode buffer.\n");
169a86c7d0aSMichael Lotz QRcode_clearCache();
170a86c7d0aSMichael Lotz return 1;
171a86c7d0aSMichael Lotz }
172a86c7d0aSMichael Lotz } else {
173a86c7d0aSMichael Lotz copyCount = inputLength < encodeLength ? inputLength : encodeLength;
1740948c0ffSMichael Lotz memcpy(sEncodeBuffer, source, copyCount);
1750948c0ffSMichael Lotz sEncodeBuffer[copyCount] = 0;
176a86c7d0aSMichael Lotz }
1770948c0ffSMichael Lotz
1780948c0ffSMichael Lotz QRcode* qrCode = QRcode_encodeString8bit(sEncodeBuffer, sQRCodeVersion,
1790948c0ffSMichael Lotz sQRCodeLevel);
1800948c0ffSMichael Lotz if (qrCode == NULL) {
181a86c7d0aSMichael Lotz kprintf("Failed to encode buffer into qr code.\n");
1820948c0ffSMichael Lotz QRcode_clearCache();
1830948c0ffSMichael Lotz return 1;
1840948c0ffSMichael Lotz }
1850948c0ffSMichael Lotz
1860948c0ffSMichael Lotz source += copyCount;
1870948c0ffSMichael Lotz inputLength -= copyCount;
1880948c0ffSMichael Lotz
18939a26a0aSMichael Lotz bool doContinue = print_qrcode(qrCode, inputLength > 0);
1900948c0ffSMichael Lotz QRcode_free(qrCode);
19139a26a0aSMichael Lotz
19239a26a0aSMichael Lotz if (!doContinue) {
19339a26a0aSMichael Lotz QRcode_clearCache();
19439a26a0aSMichael Lotz abort_debugger_command();
19539a26a0aSMichael Lotz // Does not return.
19639a26a0aSMichael Lotz }
1970948c0ffSMichael Lotz }
1980948c0ffSMichael Lotz
1990948c0ffSMichael Lotz QRcode_clearCache();
2000948c0ffSMichael Lotz return 0;
2010948c0ffSMichael Lotz }
2020948c0ffSMichael Lotz
2030948c0ffSMichael Lotz
2040948c0ffSMichael Lotz static int
qrclear(int argc,char * argv[])2050948c0ffSMichael Lotz qrclear(int argc, char* argv[])
2060948c0ffSMichael Lotz {
2070948c0ffSMichael Lotz if (argc > 1 && strcmp(argv[1], "--help") == 0) {
2080948c0ffSMichael Lotz kprintf("Clears the current QR buffer.\n");
2090948c0ffSMichael Lotz return 0;
2100948c0ffSMichael Lotz }
2110948c0ffSMichael Lotz
2120948c0ffSMichael Lotz sBufferPosition = 0;
2130948c0ffSMichael Lotz sStringBuffer[0] = 0;
2140948c0ffSMichael Lotz return 0;
2150948c0ffSMichael Lotz }
2160948c0ffSMichael Lotz
2170948c0ffSMichael Lotz
2180948c0ffSMichael Lotz static int
qrflush(int argc,char * argv[])2190948c0ffSMichael Lotz qrflush(int argc, char* argv[])
2200948c0ffSMichael Lotz {
2210948c0ffSMichael Lotz if (argc > 1 && strcmp(argv[1], "--help") == 0) {
2220948c0ffSMichael Lotz kprintf("Flushes the current QR buffer by encoding QR codes from\n"
2230948c0ffSMichael Lotz "the data and then clears the QR buffer.\n");
2240948c0ffSMichael Lotz return 1;
2250948c0ffSMichael Lotz }
2260948c0ffSMichael Lotz
2270948c0ffSMichael Lotz qrencode(0, NULL);
2280948c0ffSMichael Lotz qrclear(0, NULL);
2290948c0ffSMichael Lotz return 0;
2300948c0ffSMichael Lotz }
2310948c0ffSMichael Lotz
2320948c0ffSMichael Lotz
2330948c0ffSMichael Lotz static int
qrappend(int argc,char * argv[])2340948c0ffSMichael Lotz qrappend(int argc, char* argv[])
2350948c0ffSMichael Lotz {
2360948c0ffSMichael Lotz if (argc < 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) {
2370948c0ffSMichael Lotz kprintf("%s <string>\n", argv[0]);
2380948c0ffSMichael Lotz kprintf("Appends the given string to the QR buffer. Can be used as\n"
2390948c0ffSMichael Lotz "the target of a pipe command to accumulate the output of other\n"
2400948c0ffSMichael Lotz "commands in the QR buffer.\n"
2410948c0ffSMichael Lotz "Note that this command will flush the QR buffer when it runs\n"
2420948c0ffSMichael Lotz "full to make room for the new string. This will cause QR codes\n"
2430948c0ffSMichael Lotz "to be generated while the append command still runs. As these\n"
2440948c0ffSMichael Lotz "implicit flushes only happen to make room in the buffer, the\n"
2450948c0ffSMichael Lotz "strings are afterwards appended aren't flushed, so make sure to\n"
2460948c0ffSMichael Lotz "execute the qrflush command to generate codes for these as\n"
2470948c0ffSMichael Lotz "well.\n");
2480948c0ffSMichael Lotz return 1;
2490948c0ffSMichael Lotz }
2500948c0ffSMichael Lotz
2510948c0ffSMichael Lotz const char* source = argv[1];
2520948c0ffSMichael Lotz int length = strlen(source) + 1;
2530948c0ffSMichael Lotz
2540948c0ffSMichael Lotz while (length > 0) {
2550948c0ffSMichael Lotz int copyCount = sizeof(sStringBuffer) - sBufferPosition - 1;
2560948c0ffSMichael Lotz if (copyCount == 0) {
2570948c0ffSMichael Lotz // The buffer is full, we need to flush it.
2580948c0ffSMichael Lotz qrflush(0, NULL);
2590948c0ffSMichael Lotz }
2600948c0ffSMichael Lotz
2610948c0ffSMichael Lotz if (length < copyCount)
2620948c0ffSMichael Lotz copyCount = length;
2630948c0ffSMichael Lotz
2640948c0ffSMichael Lotz memcpy(sStringBuffer + sBufferPosition, source, copyCount);
2650948c0ffSMichael Lotz sBufferPosition += copyCount;
2660948c0ffSMichael Lotz source += copyCount;
2670948c0ffSMichael Lotz length -= copyCount;
2680948c0ffSMichael Lotz }
2690948c0ffSMichael Lotz
2700948c0ffSMichael Lotz // Overwrite the 0 byte that was copied extra with a newline.
2710948c0ffSMichael Lotz if (sBufferPosition > 0)
2720948c0ffSMichael Lotz sStringBuffer[sBufferPosition - 1] = '\n';
2730948c0ffSMichael Lotz
2740948c0ffSMichael Lotz return 0;
2750948c0ffSMichael Lotz }
2760948c0ffSMichael Lotz
2770948c0ffSMichael Lotz
2780948c0ffSMichael Lotz static int
qrconfig(int argc,char * argv[])2790948c0ffSMichael Lotz qrconfig(int argc, char* argv[])
2800948c0ffSMichael Lotz {
2810948c0ffSMichael Lotz if (argc < 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) {
2820948c0ffSMichael Lotz kprintf("%s <version>\n", argv[0]);
2830948c0ffSMichael Lotz kprintf("Sets the QR version to be used. Valid versions range from 1\n"
2840948c0ffSMichael Lotz "to 40 where each version determines the size of the QR code.\n"
2850948c0ffSMichael Lotz "Version 1 is 21x21 in size and each version increments that size\n"
2860948c0ffSMichael Lotz "by 4x4 up to 177x177 for version 40.\n"
2870948c0ffSMichael Lotz "Bigger QR codes can hold more data, so ideally you use a version\n"
2880948c0ffSMichael Lotz "that makes the QR code as big as possible while still fitting on\n"
2890948c0ffSMichael Lotz "your screen.\n"
2900948c0ffSMichael Lotz "You can test the new config by running qrencode\n"
2910948c0ffSMichael Lotz "with a test string.\n"
2920948c0ffSMichael Lotz "Note that due to memory constraints in the kernel debugger, some\n"
2930948c0ffSMichael Lotz "of the higher versions may actually not work. The kernel\n"
2940948c0ffSMichael Lotz "debugger heap size can be adjusted using the KDEBUG_HEAP define\n"
2950948c0ffSMichael Lotz "in the kernel_debug_config.h header\n");
2960948c0ffSMichael Lotz return 1;
2970948c0ffSMichael Lotz }
2980948c0ffSMichael Lotz
2990948c0ffSMichael Lotz int newVersion = atoi(argv[1]);
3000948c0ffSMichael Lotz if (newVersion <= 0 || newVersion > 40) {
3010948c0ffSMichael Lotz kprintf("Invalid QR code version supplied, "
3020948c0ffSMichael Lotz "must be between 1 and 40.\n");
3030948c0ffSMichael Lotz return 1;
3040948c0ffSMichael Lotz }
3050948c0ffSMichael Lotz
3060948c0ffSMichael Lotz sQRCodeVersion = newVersion;
3070948c0ffSMichael Lotz return 0;
3080948c0ffSMichael Lotz }
3090948c0ffSMichael Lotz
3100948c0ffSMichael Lotz
311a86c7d0aSMichael Lotz static int
qrwebpost(int argc,char * argv[])312a86c7d0aSMichael Lotz qrwebpost(int argc, char* argv[])
313a86c7d0aSMichael Lotz {
314a86c7d0aSMichael Lotz if (argc >= 3 && strcmp(argv[1], "start") == 0) {
315a86c7d0aSMichael Lotz strlcpy(sWebPostId, argv[2], sizeof(sWebPostId));
316a86c7d0aSMichael Lotz sWebPostCounter = 0;
317a86c7d0aSMichael Lotz
318a86c7d0aSMichael Lotz // Generate the clear code.
319a86c7d0aSMichael Lotz const char* args[2] = { "", "yes" };
320a86c7d0aSMichael Lotz qrencode(2, (char**)args);
321a86c7d0aSMichael Lotz } else if (argc >= 2 && strcmp(argv[1], "stop") == 0) {
322a86c7d0aSMichael Lotz sWebPostId[0] = 0;
323a86c7d0aSMichael Lotz } else {
324a86c7d0aSMichael Lotz kprintf("%s start <id>\n", argv[0]);
325a86c7d0aSMichael Lotz kprintf("%s stop\n", argv[0]);
326a86c7d0aSMichael Lotz kprintf("Causes the QR codes to be rendered as URLs that resolve to\n"
327a86c7d0aSMichael Lotz "a service that allows appending the data of multiple QR codes\n"
328a86c7d0aSMichael Lotz "for easier handling.\n"
329a86c7d0aSMichael Lotz "An initial QR code is generated that invokes a clear operation\n"
330a86c7d0aSMichael Lotz "to prepare the output file on the server.\n"
331a86c7d0aSMichael Lotz "Note that there is no logic behind the service, if you and\n"
332a86c7d0aSMichael Lotz "someone else use the same id at the same time, they will\n"
333a86c7d0aSMichael Lotz "overwrite eachother. Therefore use a reasonably unique name.\n");
334a86c7d0aSMichael Lotz return 1;
335a86c7d0aSMichael Lotz }
336a86c7d0aSMichael Lotz
337a86c7d0aSMichael Lotz return 0;
338a86c7d0aSMichael Lotz }
339a86c7d0aSMichael Lotz
340a86c7d0aSMichael Lotz
3410948c0ffSMichael Lotz static status_t
std_ops(int32 op,...)3420948c0ffSMichael Lotz std_ops(int32 op, ...)
3430948c0ffSMichael Lotz {
3440948c0ffSMichael Lotz switch (op) {
3450948c0ffSMichael Lotz case B_MODULE_INIT:
3460948c0ffSMichael Lotz add_debugger_command("qrencode", qrencode,
3470948c0ffSMichael Lotz "encodes a string / the current QR buffer");
3480948c0ffSMichael Lotz add_debugger_command("qrappend", qrappend,
3490948c0ffSMichael Lotz "appends a string to the QR buffer");
3500948c0ffSMichael Lotz add_debugger_command("qrclear", qrclear,
3510948c0ffSMichael Lotz "clears the current QR buffer");
3520948c0ffSMichael Lotz add_debugger_command("qrflush", qrflush,
3530948c0ffSMichael Lotz "encodes the current QR buffer and clears it");
3540948c0ffSMichael Lotz add_debugger_command("qrconfig", qrconfig,
3550948c0ffSMichael Lotz "sets the QR code version to be used");
356a86c7d0aSMichael Lotz add_debugger_command("qrwebpost", qrwebpost,
357a86c7d0aSMichael Lotz "sets up URL encoding for QR codes");
3580948c0ffSMichael Lotz return B_OK;
3590948c0ffSMichael Lotz case B_MODULE_UNINIT:
3600948c0ffSMichael Lotz remove_debugger_command("qrencode", qrencode);
3610948c0ffSMichael Lotz remove_debugger_command("qrappend", qrappend);
3620948c0ffSMichael Lotz remove_debugger_command("qrclear", qrclear);
3630948c0ffSMichael Lotz remove_debugger_command("qrflush", qrflush);
3640948c0ffSMichael Lotz remove_debugger_command("qrconfig", qrconfig);
365a86c7d0aSMichael Lotz remove_debugger_command("qrwebpost", qrwebpost);
3660948c0ffSMichael Lotz return B_OK;
3670948c0ffSMichael Lotz }
3680948c0ffSMichael Lotz
3690948c0ffSMichael Lotz return B_BAD_VALUE;
3700948c0ffSMichael Lotz }
3710948c0ffSMichael Lotz
3720948c0ffSMichael Lotz
3730948c0ffSMichael Lotz static struct debugger_module_info sModuleInfo = {
3740948c0ffSMichael Lotz {
3750948c0ffSMichael Lotz "debugger/qrencode/v1",
3760948c0ffSMichael Lotz 0,
3770948c0ffSMichael Lotz &std_ops
3780948c0ffSMichael Lotz },
3790948c0ffSMichael Lotz NULL,
3800948c0ffSMichael Lotz NULL,
3810948c0ffSMichael Lotz NULL,
3820948c0ffSMichael Lotz NULL
3830948c0ffSMichael Lotz };
3840948c0ffSMichael Lotz
3850948c0ffSMichael Lotz module_info *modules[] = {
3860948c0ffSMichael Lotz (module_info *)&sModuleInfo,
3870948c0ffSMichael Lotz NULL
3880948c0ffSMichael Lotz };
3890948c0ffSMichael Lotz
390