1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Support for the Matrox "lspci" channel
4 Copyright (C) 2005 Matrox Graphics Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <sys/types.h>
25 static VCHANNEL
*lspci_channel
;
27 typedef struct _pci_device
38 static pci_device current_device
;
40 static void lspci_send(RDPCLIENT
* This
, const char *output
);
43 /* Handle one line of output from the lspci subprocess */
45 handle_child_line(RDPCLIENT
* This
, const char *line
, void *data
)
50 if (str_startswith(line
, "Class:"))
52 val
= line
+ sizeof("Class:");
53 /* Skip whitespace and second Class: occurance */
54 val
+= strspn(val
, " \t") + sizeof("Class");
55 current_device
.klass
= strtol(val
, NULL
, 16);
57 else if (str_startswith(line
, "Vendor:"))
59 val
= line
+ sizeof("Vendor:");
60 current_device
.vendor
= strtol(val
, NULL
, 16);
62 else if (str_startswith(line
, "Device:"))
64 val
= line
+ sizeof("Device:");
65 /* Sigh, there are *two* lines tagged as Device:. We
66 are not interested in the domain/bus/slot/func */
67 if (!strchr(val
, ':'))
68 current_device
.device
= strtol(val
, NULL
, 16);
70 else if (str_startswith(line
, "SVendor:"))
72 val
= line
+ sizeof("SVendor:");
73 current_device
.subvendor
= strtol(val
, NULL
, 16);
75 else if (str_startswith(line
, "SDevice:"))
77 val
= line
+ sizeof("SDevice:");
78 current_device
.subdevice
= strtol(val
, NULL
, 16);
80 else if (str_startswith(line
, "Rev:"))
82 val
= line
+ sizeof("Rev:");
83 current_device
.revision
= strtol(val
, NULL
, 16);
85 else if (str_startswith(line
, "ProgIf:"))
87 val
= line
+ sizeof("ProgIf:");
88 current_device
.progif
= strtol(val
, NULL
, 16);
90 else if (strspn(line
, " \t") == strlen(line
))
92 /* Blank line. Send collected information over channel */
93 snprintf(buf
, sizeof(buf
), "%04x,%04x,%04x,%04x,%04x,%02x,%02x\n",
94 current_device
.klass
, current_device
.vendor
,
95 current_device
.device
, current_device
.subvendor
,
96 current_device
.subdevice
, current_device
.revision
, current_device
.progif
);
97 lspci_send(This
, buf
);
98 memset(¤t_device
, 0, sizeof(current_device
));
102 warning("lspci: Unrecoqnized line '%s'\n", line
);
108 /* Process one line of input from virtual channel */
110 lspci_process_line(RDPCLIENT
* This
, const char *line
, void *data
)
112 char *lspci_command
[5] = { "lspci", "-m", "-n", "-v", NULL
};
114 if (!strcmp(line
, "LSPCI"))
116 memset(¤t_device
, 0, sizeof(current_device
));
117 subprocess(This
, lspci_command
, handle_child_line
, NULL
);
118 /* Send single dot to indicate end of enumeration */
119 lspci_send(This
, ".\n");
123 error("lspci protocol error: Invalid line '%s'\n", line
);
129 /* Process new data from the virtual channel */
131 lspci_process(RDPCLIENT
* This
, STREAM s
)
134 static char *rest
= NULL
;
137 pkglen
= s
->end
- s
->p
;
138 /* str_handle_lines requires null terminated strings */
139 buf
= xmalloc(pkglen
+ 1);
140 STRNCPY(buf
, (char *) s
->p
, pkglen
+ 1);
142 printf("lspci recv:\n");
143 hexdump(s
->p
, pkglen
);
146 str_handle_lines(This
, buf
, &rest
, lspci_process_line
, NULL
);
150 /* Initialize this module: Register the lspci channel */
152 lspci_init(RDPCLIENT
* This
)
155 channel_register(This
, "lspci", CHANNEL_OPTION_INITIALIZED
| CHANNEL_OPTION_ENCRYPT_RDP
,
157 return (lspci_channel
!= NULL
);
160 /* Send data to channel */
162 lspci_send(RDPCLIENT
* This
, const char *output
)
167 len
= strlen(output
);
168 s
= channel_init(This
, lspci_channel
, len
);
169 out_uint8p(s
, output
, len
) s_mark_end(s
);
172 printf("lspci send:\n");
173 hexdump(s
->channel_hdr
+ 8, s
->end
- s
->channel_hdr
- 8);
176 channel_send(This
, s
, lspci_channel
);